von phi » Do 3. Feb 2011, 18:13
Hallo,
eine umfassende Erklärung wäre relativ schwierig. Falls du dich für die Details interessierst, kommst du um die Lektüre eines Buches, welches die TeX-Interna erklärt, nicht herum, beispielsweise
TeX by Topic.
Bei der Expansion eines Makros („Befehl“ in LaTeX-Sprechweise) werden Parametertoken wie #1 durch die entsprechenden Argumente ersetzt, bevor irgendeine andere Verarbeitung stattfindet. D.h. \myif{} wird ersetzt durch
\def\val{}
\newcommand{\cmd}{}
**** ifx **** \\
\#1 \ifx\empty leer \else voll \fi \\
val \ifx\val\empty leer \else voll \fi \\
cmd \ifx\cmd\empty leer \else voll \fi \\
**** ifstr **** \\
\#1 \ifstr{}{}{leer}{voll} \\
val \ifstr{\val}{}{leer}{voll} \\
cmd \ifstr{\cmd}{}{leer}{voll} \\
\ifx überprüft nun, ob die beiden darauffolgenden Token die gleiche Bedeutung haben. Im ersten Fall vergleicht \ifx die Bedeutung des Makros \empty mit dem Buchstaben „l“ (denn das sind die beiden folgenden Token, das #1 ist durch die Makro-Ersetzung komplett verschwunden!), diese sind natürlich nicht gleich, und der Vergleich expandiert zum \else-Zweig.
Im zweiten Fall werden die beiden Makros \val und \empty verglichen. Da \empty als
definiert ist, sind diese Token gleich, und die Expansion ist „leer“.
Im dritten Fall werden die beiden Makros \cmd und \empty verglichen. Da der LaTeX-Befehl \newcommand das zu definierende Makro als \long definiert (d.h. es akzeptiert Argumente, die Absatzendetoken enthalten) und \ifx auch den \long-Status von Makros vergleicht, sind diese beiden Makros ebenfalls nicht gleich.
Wenn du in einem Makro überprüfen willst, ob ein übergebenes Argument leer ist, musst du erst definieren, was als „leer“ gilt. Vier häufig anzutreffende Definitionen sind:
- Ein Argument gilt als leer, wenn es keine Token enthält.
- Ein Argument gilt als leer, wenn es ausschließlich Leerzeichentoken enthält, beispielsweise „ “ (ein einzelnes explizites Leerzeichen).
- Ein Argument gilt als leer, wenn seine vollständige Expansion keine Token enthält, beispielsweise „\empty“.
- Ein Argument gilt als leer, wenn seine vollständige Expansion ausschließlich Leerzeichentoken enthält, beispielsweise „\space“.
(1) ist ein Spezialfall von (2), (3) und (4); (2) ist ein Spezialfall von (4); (3) ist ebenfalls ein Spezialfall von (4). Dein Vergleich \ifx\val\empty verwendet Bedingung (1); die Tests mit \ifstr verwenden Bedingung (3); \ifstrempty aus dem etoolbox-Paket verwendet Bedingung (1) (ist allerdings expandierbar), \ifblank verwendet Bedingung (2). D.h. \ifstr arbeitet nur dann „richtig“ (aus deiner Sicht), wenn du tatsächlich auf Bedingung (3) testen willst.
Hallo,
eine umfassende Erklärung wäre relativ schwierig. Falls du dich für die Details interessierst, kommst du um die Lektüre eines Buches, welches die TeX-Interna erklärt, nicht herum, beispielsweise [url=http://eijkhout.net/texbytopic/texbytopic.html]TeX by Topic[/url].
Bei der Expansion eines Makros („Befehl“ in LaTeX-Sprechweise) werden Parametertoken wie #1 durch die entsprechenden Argumente ersetzt, bevor irgendeine andere Verarbeitung stattfindet. D.h. \myif{} wird ersetzt durch
[code]\def\val{}
\newcommand{\cmd}{}
**** ifx **** \\
\#1 \ifx\empty leer \else voll \fi \\
val \ifx\val\empty leer \else voll \fi \\
cmd \ifx\cmd\empty leer \else voll \fi \\
**** ifstr **** \\
\#1 \ifstr{}{}{leer}{voll} \\
val \ifstr{\val}{}{leer}{voll} \\
cmd \ifstr{\cmd}{}{leer}{voll} \\
[/code]
\ifx überprüft nun, ob die beiden darauffolgenden Token die gleiche Bedeutung haben. Im ersten Fall vergleicht \ifx die Bedeutung des Makros \empty mit dem Buchstaben „l“ (denn das sind die beiden folgenden Token, das #1 ist durch die Makro-Ersetzung komplett verschwunden!), diese sind natürlich nicht gleich, und der Vergleich expandiert zum \else-Zweig.
Im zweiten Fall werden die beiden Makros \val und \empty verglichen. Da \empty als
[code]\def\empty{}[/code]
definiert ist, sind diese Token gleich, und die Expansion ist „leer“.
Im dritten Fall werden die beiden Makros \cmd und \empty verglichen. Da der LaTeX-Befehl \newcommand das zu definierende Makro als \long definiert (d.h. es akzeptiert Argumente, die Absatzendetoken enthalten) und \ifx auch den \long-Status von Makros vergleicht, sind diese beiden Makros ebenfalls nicht gleich.
Wenn du in einem Makro überprüfen willst, ob ein übergebenes Argument leer ist, musst du erst definieren, was als „leer“ gilt. Vier häufig anzutreffende Definitionen sind:
[list=1][*]Ein Argument gilt als leer, wenn es keine Token enthält.
[*]Ein Argument gilt als leer, wenn es ausschließlich Leerzeichentoken enthält, beispielsweise „ “ (ein einzelnes explizites Leerzeichen).
[*]Ein Argument gilt als leer, wenn seine vollständige Expansion keine Token enthält, beispielsweise „\empty“.
[*]Ein Argument gilt als leer, wenn seine vollständige Expansion ausschließlich Leerzeichentoken enthält, beispielsweise „\space“.[/list](1) ist ein Spezialfall von (2), (3) und (4); (2) ist ein Spezialfall von (4); (3) ist ebenfalls ein Spezialfall von (4). Dein Vergleich \ifx\val\empty verwendet Bedingung (1); die Tests mit \ifstr verwenden Bedingung (3); \ifstrempty aus dem etoolbox-Paket verwendet Bedingung (1) (ist allerdings expandierbar), \ifblank verwendet Bedingung (2). D.h. \ifstr arbeitet nur dann „richtig“ (aus deiner Sicht), wenn du tatsächlich auf Bedingung (3) testen willst.