Das folgende Codebeispiel zeigt zwei Vergleiche mit unterschiedlichem Ergebnis.

\documentclass{article}
\usepackage{expl3}
\begin{document}
Vergleich mit plain-\TeX:
\ifx{\ss}\ss gleich\else ungleich\fi

Vergleich mit expl3:
\ExplSyntaxOn
\token_if_eq_meaning:NNTF {\ss} \ss {gleich} {ungleich}
\ExplSyntaxOff
\end{document}

Der erste Vergleich ergibt „ungleich“. Dies entspricht meiner Erwartung, da ich davon ausgehe, dass hier nicht {\ss} und \ss miteinander verglichen werden, sondern { und \ss, da dies die ersten beiden Token nach \ifx sind.

Der zweite Vergleich ergibt „gleich“. Dies scheint zwar semantisch sinnvoll, ist aber überraschend, denn erstens ist \token_if_eq_meaning:NNTF mit Hilfe von \ifx definiert, wie man dem Dokument source3 entnehmen kann, sollte sich also genauso verhalten. Zweitens verbietet die expl3-Anleitung die Verwendung geschweifter Klammern für N-Argumente.

Wieso ergeben beide Vergleiche unterschiedliche Ergebnisse?

Ich komme aus folgendem Grund auf die Frage: Eine Funktion mit N-Argument könnte missbräuchlich mit einem Argument in geschweiften Klammern aufgerufen werden. Dann würde aber der \token_if_eq_meaning:NNTF-Befehl, der innerhalb dieser Funktion auftritt durcheinander kommen.

\documentclass{article}
\usepackage{expl3}
\begin{document}
\ExplSyntaxOn
\cs_new:Npn \meinbefehl:N #1
  {
    \token_if_eq_meaning:NNTF #1 \ss {Eszett~gelesen} {kein~Eszett~gelesen}
  }
\meinbefehl:N a
\par
\meinbefehl:N \ss
\par
\meinbefehl:N {ab}
\ExplSyntaxOff
\end{document}

Der dritte Aufruf von \meinbefehl:N ergibt „Eszett gelesenkein Eszett gelesen“. Hier wird offenbar nicht ab mit \ss verglichen, sondern a mit b, sodass der True-Code zum False-Code wird und der False-Code nicht mehr als Befehlsargument aufgefasst wird und somit einfach angehängt wird. Ich habe mich nun gefragt, ob es sinnvoll wäre, das unerwünschte Verhalten durch geschweifte Klammern auszuschließen:

\token_if_eq_meaning:NNTF {#1} \ss {Eszett~gelesen} {kein~Eszett~gelesen}

Das scheint zu funktionieren, die Frage ist nur, ob man sich darauf verlassen kann.

gefragt 14 Apr '20, 13:14

Cletus's gravatar image

Cletus
1.6k45566
Akzeptiert-Rate: 75%

bearbeitet 14 Apr '20, 13:17


Die scheinbar unterschiedlichen Ergebnisse ergeben sich aus der Tatsache, dass \token_if_eq_meaning:NNTF ein Makro ist und daraus, wie Makros ihre Argumente lesen.

Du hast recht: \ifx vergleicht die zwei als nächstes folgenden Token, das heißt im Fall von

\ifx{\ss}\ss ...\else...\fi

dass { mit \ss verglichen wird. Das sind zwei Token mit verschiedenem „Meaning“, also ist das Ergebnis falsch. Hier siehst du's auch nochmal:

1: \ifx{\ss}\ss gleich\else ungleich\fi % ungleich

2: \ifx\ss\ss gleich\else ungleich\fi   % gleich

\end

Warum funktioniert's dann mit \token_if_eq_meaning:NNTF? Antwort: weil es ein Makro ist und ein Makro als Argument entweder ein Token nimmt oder eine „braced group“ und dabei das äußere Paar „Braces“ entfernt. Darum gibt hier alles „gleich“:

\long\def\firstoftwo#1#2{#1}
\long\def\secondoftwo#1#2{#2}
\def\tokenifeqmeaning#1#2{%
  \ifx#1#2\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
}

1: \tokenifeqmeaning{\ss}\ss{gleich}{ungleich}   % gleich

2: \tokenifeqmeaning\ss\ss{gleich}{ungleich}     % gleich

2: \tokenifeqmeaning{\ss}{\ss}{gleich}{ungleich} % gleich

\end

Noch was zu expl3: ein N als Argument Specifier bedeutet immer nimm ein Token und keine braced group, im Gegensatz zu n, das genau das Gegenteil bedeutet. Als Code-Schreiber sollte man da drauf achten und User-Input ggf vorab „bearbeiten“, damit man der Funktion das richtige zu essen gibt. Man darf sich nicht auf die Implementierung einer „Funktion“ verlassen, sondern nur auf ihre dokumentierte Funktionsweise.

Man könnte nun zwar mit einigem Recht behaupten, dass \token_if_eq_meaning:NNTF {\ss} das falsche Ergebnis liefert, da .{ und \ss nun mal nicht gleich sind, aber es ist dokumentiert, dass das nicht geht:

Note that an explicit begin group token cannot be tested in this way, as it is not a valid N-type argument.

Das heißt nichts anderes als, dass \token_if_eq_meaning:NNTF {\ss} falsche Anwendung ist. Das gleiche gilt für \meinbefehl:N {ab}. Das ist ebenfalls eine falsche Anwendung. Dass dann was anderes herauskommt als erwartet, sollte nicht überraschen.

Permanenter link

beantwortet 14 Apr '20, 19:21

cgnieder's gravatar image

cgnieder
22.1k243463
Akzeptiert-Rate: 60%

bearbeitet 14 Apr '20, 20:12

Danke, das hilft mir. Um missbräuchliche Nutzung von N-Argumenten zu unterbinden, scheint \tl_if_single_token:nTF geeignet zu sein.

(14 Apr '20, 21:09) Cletus
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:

×13
×5
×1

gestellte Frage: 14 Apr '20, 13:14

Frage wurde gesehen: 2,651 Mal

zuletzt geändert: 14 Apr '20, 21:09