5
1

Im Internet taucht immer wieder LaTeX-Code auf, bei dem beispielsweise Schriftgrößenbefehle wie \large oder der Befehl zur Umschaltung auf den Anhang, \appendix, statt als Befehl als Umgebung mit \begin{…}…\end{…} geschrieben wird. Geht das eigentlich bei allen Befehlen und kann man das unbesorgt tun? Und wie ist es mit dem umgekehrten Fall, also der Verwendung einer Umgebung als Anweisung?

gefragt 11 Okt '13, 08:42

saputello's gravatar image

saputello
11.1k174365
Akzeptiert-Rate: 51%

bearbeitet 11 Okt '13, 09:48


Hintergrund:

TeX selbst, also die Makrosprache hinter LaTeX, kennt keine Umgebungen. Umgebungen werden daher intern als zwei Befehle repräsentiert: einem Befehl für den bei \begin auszuführenden Start-Code und einen weiteren Befehl für den bei \end auszuführenden Ende-Code. Bei LaTeX 2.09, dem Vorläufer des heute als LaTeX bezeichneten LaTeX2e, hat Leslie Lamport, der Erfinder von LaTeX, entschieden, diese beiden Befehle für eine Umgebung foo einfach als \foo und \endfoo zu definieren. Gleichzeitig wird zwar in \begin{foo} von \begin getestet, ob der Befehl \foo definiert ist, und anderenfalls ein Fehler wegen einer nicht definierten Umgebung ausgegeben. Aber weder in \begin{foo} noch in \end{foo} findet ein Test statt, ob auch ein \endfoo definiert ist. Aus Gründen der Kompatibilität wurde diese Designentscheidung bei der Implementierung von LaTeX2e übernommen.

Daraus ergeben sich einige Seiteneffekte:

  • Man kann eine Umgebung foo, die keinen Ende-Code benötigen, auch einfach als Anweisung \foo definieren.
  • Man kann eine Umgebung foo auch als Anweisungen \foo und \endfoo implementieren.
  • Anwender können als Argument bei \begin den Namen jeder Anweisung angeben, ohne dass LaTeX deshalb eine nicht definierte Umgebung meldet.
  • Anwender können den Start-Code von Umgebungen auch als Anweisung aufrufen, ohne dass deshalb eine nicht definierte Anweisung gemeldet wird.

Allerdings stellt sich die Frage nach ungünstigen Nebenwirkungen.

Definition als Anweisungen statt als Umgebung:

Bei der Definition von Umgebungen als Anweisungen ergibt sich im ersten Fall kein Problem. Im zweiten Fall hat man aber bereits das Problem, dass eine Anweisung, die mit \end beginnt über \newcommand gar nicht definiert werden kann. LaTeX meldet hier einen Fehler:

Open in Online-Editor
\newcommand*{\endfoo}{}

ergibt:

Open in Online-Editor
! LaTeX Error: Command \endfoo already defined.
           Or name \end... illegal, see p.192 of the manual.

Man müsste zur Definition also die LaTeX-Ebene verlassen und sich mit \def auf die TeX-Ebene hinab begeben. Daraus ergibt sich für mich: Man sollte zur Implementierung einer Umgebung nach Möglichkeit immer die dafür vorgesehenen LaTeX-Anweisungen, beispielsweise \newenvironment, verwenden.

Verwendung einer Anweisung als Umgebung:

Bei der Verwendung einer Anweisung als Umgebung ergeben sich ebenfalls Probleme. Normalerweise sind Umgebungen gleichzeitig Gruppen. Ein zentrales Kennzeichen einer Gruppe ist, dass Änderungen innerhalb der Gruppe am Ende der Gruppe wieder aufgehoben sind. Das sollte daher auch für Umgebungen gelten. So verändern beispielsweise Listenumgebungen den Einzug, der aber am Ende der Umgebung wieder zurückgesetzt ist, Umgebungen für Theoreme ändern möglicherweise die Schrift, die aber nach dem Ende der Umgebung wieder die vorherige Einstellung hat. Es gibt aber beispielsweise Anweisungen, deren Wirkung global ist. So definiert, beispielsweise die in der Frage erwähnte Anweisung \appendix bei den meisten Klassen die Darstellung des Kapitelzählers global um. Missbraucht man die Anweisung als Umgebung, so endet ihre Wirkung daher nicht mit den Ende der Umgebung. Beispielsweise wird bei:

Open in Online-Editor
\documentclass{article}

\begin{document}
\section{Erster Abschnitt}

\begin{appendix}% ACHTUNG, DAS IST FALSCH!!!
\section{Erster Anhang}

\section{Zweiter Anhang}
\end{appendix}

\section{Zweiter Abschnitt}

\end{document}

Der zweite Abschnitt keineswegs mit einer 2 nummeriert, wie man das nach Verlassen der Umgebung appendix erwarten würde. Stattdessen bekommt man:

unerwartetes Ergebnis

Der zweite Abschnitt ist also in Wirklichkeit Anhang C.

Darüber hinaus gibt es ggf. weitere Auswirkungen zu beachten, wie sie beispielsweise bei der Frage »Kann ich Schriftgrößenumschaltungen auch als Umgebungen verwenden?« behandelt werden. Daraus ergibt sich für mich: Man sollte einen Befehl nicht als Umgebung missbrauchen.

Verwendung einer Umgebung als Anweisung(en):

Bei der Verwendung einer Umgebung als Anweisung ohne Ende-Anweisung ergeben sich zwangsläufig Probleme. So würde eine mit \enumerate begonnene Listenumgebung ohne Ende-Anweisung natürlich niemals enden und der gesamte weitere Text als Teil der Listenumgebung formatiert. Aber auch mit Ende-Anweisung können sich Probleme ergeben. Wie bereits erwähnt beinhaltet eine Umgebung normalerweise auch eine Gruppe. Zwar enthalten die Start- und Ende-Anweisungen einiger Umgebungen auch noch zusätzliche explizite Gruppen, die eigentliche Gruppe wird aber von \begin und \end selbst aufgespannt. Verwendet man eine Umgebung nun also nur in Form ihrer Start- und Ende-Anweisung statt mit \begin und \end bleibt die Wirkung wie im folgenden Beispiel teilweise nach der Ende-Anweisung erhalten:

Open in Online-Editor
\documentclass{article}

\begin{document}
\section{Erster Abschnitt}

\begin{enumerate}
\item erster Eintrag
\item zweiter Eintrag
\end{enumerate}

\label{sec:erster}
Dies ist Abschnitt~\ref{sec:erster}.

\enumerate
\item erster Eintrag
\item zweiter Eintrag
\endenumerate

\label{sec:nocherster}
Dies ist Abschnitt~\ref{sec:nocherster}.

\end{document}

falsche Formatierung und Referenz

Wie zu sehen ist, ist nicht nur die zweite Referenz falsch – sie bezieht sich noch auf den zweiten Eintrag der \enumerate…\endenumerate-Liste – auch der Einzug des zweiten Satzes orientiert sich noch an \item. Im Übrigen werden so Schachtelfehler bei Umgebungen nicht mehr erkannt, wie das beispielsweise bei:

Open in Online-Editor
\begin{figure}
  \begin{enlighted}
  \end{figure}
\end{enlighted}

der Fall wäre. Daraus ergibt sich für mich: Man kann und sollte auf Anwenderebene eine Umgebung nicht einfach nur durch ihre Start-Anweisung und ihre End-Anweisung ersetzen.

Geplante Änderungen bei LaTeX3:

Mit LaTeX3 wird sich diesbezüglich übrigens eine wichtige Änderung ergeben. Bei LaTeX3 wird intern einer Umgebung foo nicht mehr durch die Befehle \foo und \endfoo, sondern durch die Befehle \environment foo, \environment foo end und das zusätzliche, in \environment foo end verwendete \environment foo end aux (als interne Anweisungen der Implementierungsebene haben sie tatsächlich Leerzeichen in den Befehlsnamen) repräsentiert. Dadurch ist es dann auch nicht mehr möglich, Befehle als Umgebungen zu missbrauchen oder versehentlich den Anfang einer Umgebung als Befehl zu verwenden, wie wir das bei center häufiger erleben. Bereits heute werden diese neuen Anweisungen von den xparse-Anweisungen zur Definition von Umgebungen: \DeclareDocumentEnvironment, \NewDocumentEnvironment, \RenewDocumentEnvironment und \ProvideDocumentEnvironment, entsprechend definiert. Da xparse derzeit aber nicht nur die LaTeX3-Schnittstelle zur Definition von Anwenderanweisungen und Umgebungen bereitstellt, sondern auch noch für die Kompatibilität zu LaTeX2e sorgen muss, werden derzeit auch weiterhin \foo und \endfoo definiert.

Fazit:

Aufgrund der Implementierung von Umgebungen ist es in LaTeX2e zwar syntaktisch möglich, Anweisungen als Umgebung zu verwenden oder die Start- oder Endeanweisungen einiger Umgebungen auch auf Anwenderebene zu verwenden, aufgrund des dadurch eröffneten Fehlerpotentials sollte man dies jedoch vermeiden.

Permanenter link

beantwortet 11 Okt '13, 09:44

saputello's gravatar image

saputello
11.1k174365
Akzeptiert-Rate: 51%

bearbeitet 04 Feb '15, 10:32

cgnieder's gravatar image

cgnieder
22.1k253463

@saputello - Ich habe gerade bemerkt dass Du Deine eigene Frage bereits beantwortet (und auch akzeptiert) hast, während ich noch dabei war eine separate Antwort zu schreiben. Soll ich meine Antwort löschen?

(11 Okt '13, 10:13) Mico
1

@Mico Fragen – auch meine, die ich in der Regel selbst beantworte ­– vertragen durchaus mehr als eine Antwort. Du kannst ja warten, bis Du drei positive Bewertungen hast. Dann bekommst Du fürs Löschen die Medaille Diszipliniert. ;)

(11 Okt '13, 17:45) saputello

LaTeX-intern sind Umgebungen als Befehlspaare definiert. Siehe z.B. die Umgebung center: Beim Auffinden der Anweisung \begin{center} wird der Befehl \center ausgeführt, welcher (siehe latex.ltx) als

\trivlist \centering\item\relax

definiert ist; und beim Auffinden der Anweisung \end{center} wird der Befehl \endcenter ausgeführt, welcher (siehe wieder latex.ltx) als

 \endtrivlist

definiert ist. Man beachte dass die Umgebung trivlist -- begonnen und beendet via \trivlist und \endtrivlist -- implizit in der Umgebung center enthalten ist

Man kann diese Situation auch umkehren und einen einfachen Befehl, z.B. \large, wie eine Umgebung einsetzen, d.h., als \begin{large} ... \end{large}, selbst wenn die Umgebung large per se nicht definiert ist. Warum endet solches Tun nicht mit Fehlermeldung und Absturz? Wenn LaTeX die Anweisung \begin{large} findet, wird \large ausgeführt. Und was passiert wenn LaTeX \end{large} auffindet? Antwort: Nichts; genauer gesagt: nichts Schlimmes. Beim Auffinden von \end{large} wird nicht \endlarge ausgeführt sondern \csname large \endcsname. (cs is kurz für control sequence.) Nun hat TeX hat eine (sehr nützliche!) Regel dass eine nicht definierte control sequence wie \relax wirkt...

Man kann also in den meisten Fällen (aber schon nicht ganz beliebig!) eine Umgebung mit dem Namen eines normalen Befehls (aber ohne dem backslash Zeichen \) verwenden. Der Befehl muss natürlich existieren, sonst gibt's eine Fehlermeldung. Zu empfehlen ist diese Vorgehensweise allerdings schon nicht weil sie bei Uneingeweihten schnell Verwirrung und vielleicht sogar Bestürzen stiften wird.

Ein separates Anliegen ist: Warum gibt es in LaTeX sowohl einfache Befehle, z.B. \centering, als auch Umgebungen, z.B. \begin{center} ... \end{center}? Die Antwort kann nur sein: Um den LaTeX-Nutzern das Leben (oder wenigstens das Schreiben) zu vereinfachen. Es ist einfach nicht nötig eine appendix Umgebung zu definieren und zu verlangen dass man immer sowohl \begin{appendix} als auch \begin{appendix} schreibt; die kurze Anweisung \appendix genügt. Den LaTeX Autoren vorzuschreiben sie müssten sich stets daran erinnern die Anweisung \end{appendix} (oder \endappendix) vor Ende des Dokuments einfügen wäre nur umständliche Zwängerei. So wäre es auch gar umständlich falls man statt den einfachen Anweisungen \section{...} und \subsection{...} Umgebungen einsetzen müsste, d.h., \begin{section}{...} und \begin{subsection}{...} sowie später \end{section}{...} und \end{subsection}{...} schreiben müsste. Solche strikte Konsistenz im coding mag vielleicht der Traum gewisser Informatik-Puristen sein, aber es würde meiner Meinung nach den Endnutzern nur Umstände und Zeitverschwendung bescheren.

Permanenter link

beantwortet 11 Okt '13, 10:10

Mico's gravatar image

Mico
28513
Akzeptiert-Rate: 10%

bearbeitet 13 Okt '13, 14:03

1

Soweit ich weiß, erlaubt übrigens ConTeXt die Syntax \startsection ... \stopsection forciert sie aber nicht.

(11 Okt '13, 11:57) cgnieder

@Clemens: In MkIV wird das eigentlich durchaus propagiert, jedenfalls werden die Vorteile gegenüber \section herausgestrichen: siehe http://wiki.contextgarden.net/Command/startsection. In LaTeX ist es noch möglich, aber eigentlich nur als Nebeneffekt (siehe Erklärung oben). Was mich bei ConTeXt etwas wundert ist, dass man dann tatsächlich \startchapter, \startsection etc. hat und nicht einfach Umgebungen ineinander schachtelt und entsprechend der Schachtlungstiefe die Ebene bestimmt wird. Aber ich habe ConTeXt einfach noch nicht wirklich verstanden.

(11 Okt '13, 17:58) saputello
Deine Antwort
Vorschau umschalten

Folgen dieser Frage

Per E-Mail:

Wenn sie sich anmelden, kommen Sie für alle Updates hier in Frage

Per RSS:

Antworten

Antworten und Kommentare

Markdown-Grundlagen

  • *kursiv* oder _kursiv_
  • **Fett** oder __Fett__
  • Link:[Text](http://url.com/ "Titel")
  • Bild?![alt Text](/path/img.jpg "Titel")
  • nummerierte Liste: 1. Foo 2. Bar
  • zum Hinzufügen ein Zeilenumbruchs fügen Sie einfach zwei Leerzeichen an die Stelle an der die neue Linie sein soll.
  • grundlegende HTML-Tags werden ebenfalls unterstützt

Frage-Themen:

×52
×38
×16

gestellte Frage: 11 Okt '13, 08:42

Frage wurde gesehen: 16,844 Mal

zuletzt geändert: 04 Feb '15, 10:32