Zirkuläre Referenz im LaTeX-Makro

Zirkuläre Referenz im LaTeX-Makro

Beim Versuch, Makros in LaTeX zu lernen, stieß ich aufdiese Definition:

\x@protectist ein Makro mit einem Argument, dargestellt durch " #1". \@typeset@protectist auch definiert als \relaxund daher wird der erste Zweig von \ifxausgeführt, der nichts tut. ( \ifxvergleicht die Bedeutung zweier Makros.) Das einzige Ergebnis von \x@protectist also, dass sein Argument, das erste " \\" in der Definition von \\, verworfen wird. Übrig bleiben der Befehl \protect, der eine Nicht-Operation ist, und \\es selbst. Dies scheint eine zirkuläre Definition zu sein. Tatsächlich ist es das nicht. Es ist ein fieser Trick der LaTeX-Autoren, die versuchen, ihre Spuren zu verwischen. Werfen Sie einen zweiten, äußerst misstrauischen Blick auf die Auflistung von \\. Zwischen dem letzten " " und dem Punkt stehen zwei Leerzeichen \\, während nach der letzten Steuersequenz in anderen Auflistungen nur eins steht! Tatsächlich steht in allen Auflistungen nur ein Leerzeichen am Ende. Das vorletzte Leerzeichen in der Auflistung von \\ist Teil des Namens seiner letzten Steuersequenz, die " \\" ist, einschließlich des Leerzeichens!`

Warum der zirkuläre Verweis?

Warum bricht es nicht ab, wenn ein Zirkelverweis auftritt?

Antwort1

Beginnen wir eine interaktive Sitzung mit pdflatex test, wo test.texist

\documentclass{article}

\DeclareRobustCommand{\?}{js bibra}

\makeatletter

\show\?

Der \showBefehl stoppt den Lauf, sodass wir weitere Befehle ausgeben können

This is pdfTeX, Version 3.14159265-2.6-1.40.20 (TeX Live 2019) (preloaded format=pdflatex)
 restricted \write18 enabled.
entering extended mode
(./test.tex
LaTeX2e <2019-10-01> patch level 3
(/usr/local/texlive/2019/texmf-dist/tex/latex/base/article.cls
Document Class: article 2019/10/25 v1.4k Standard LaTeX document class
(/usr/local/texlive/2019/texmf-dist/tex/latex/base/size10.clo))
> \?=macro:
->\x@protect \?\protect \?  .
l.7 \show\?

? i\show\x@protect
> \x@protect=macro:
#1->\ifx \protect \@typeset@protect \else \@x@protect #1\fi .
<insert>   \show\x@protect

l.7 \show\?

? i\show\@x@protect
> \@x@protect=macro:
#1\fi #2#3->\fi \protect #1.
<insert>   \show\@x@protect

l.7 \show\?

Was passiert, wenn \?verarbeitet wird? Es gibt zwei Fälle: Wenn \protectnicht die gleiche Bedeutung hat wie \@typeset@protect(was ist \relax), dann wird der falsche Zweig verfolgt. Somit hat der Eingabestrom

\@x@protect\?\fi\protect\?

und die Erweiterung von \@x@protectentfernt die letzten beiden Token, sodass übrig bleibt \protect\?\fi(und \fischließlich verschwindet).

Dies geschieht beispielsweise in \protected@edefoder \protected@write, wenn \protecteine andere Bedeutung als zugewiesen wird \@typeset@protect.

Wenn dies der Fall ist, ist die Bedingung wahr, so dass der Eingabestrom nach dem Überspringen des falschen Zweigs Folgendes aufweist:

\protect\?

Jetzt \protectverschwindet und wirerscheinenan der gleichen Stelle zu sein wie vorher. Aber das sind wir nicht, denn das folgende Token \protectistandersdavon \?wurde in das Testdokument eingetragen.

Schauen Sie sich die Ausgabe des ersten \showBefehls genau an. Wir erhalten

->\x@protect \?\protect \?  .

Zwischen ->und dem abschließenden Punkt stellt TeX den Ersatztext des Makros dar. Die Regeln für diese Darstellung sind, dass auf Steuerwörter ein Leerzeichen folgt, während dies bei Steuersymbolen nicht der Fall ist. Dies erklärt das Leerzeichen nach \x@protectund \protectsowie das Fehlen eines Leerzeichens nach \?. Aber dem abschließenden Punkt geht ein Leerzeichen vorauszweiRäume! Woher kommen sie?

Wenn Sie dies tun \DeclareRobustCommand{\?}{js bibra}, führt LaTeX mehrere Aktionen aus. Die wichtigste davon ist etwa

\expandafter\def\csname ? \endcsname{js bibra}

und verwenden Sie dann dieses Makro mit einem sehr unüblichen Namen, um die „Benutzerversion“ von zu definieren \?. Beachten Sie das Leerzeichen vor \endcsname, das im Makronamen endet.

Es gibt noch ein paar weitere Details, aber die Idee ist, das Schreiben von Hilfsdateien zu erleichtern. In den älteren Versionen von LaTeX sahen wir so etwas wie

\def\LaTeX{\protect\pLaTeX}
\def\pLaTeX{<the real definition>}

Als LaTeX2e veröffentlicht wurde, wurde der bisherige Code

\DeclareRobustCommand{\LaTeX}{<the real definition>}

Nutzung einer neuen Abstraktionsebene. In den älteren Versionen \LaTeX{}hätte ein Abschnittstitel lauten müssen:

\protect\pLaTeX {}

in den Hilfsdateien. Jetzt schreibt es

\LaTeX  {}

wegen des abschließenden Leerzeichens im Namen und in der Regel. Das doppelte Leerzeichen wird beim Einlesen der Hilfsdatei ignoriert.

Bei Steuersymbolen wie \\oder verhält es sich etwas anders \?, die Grundidee ist jedoch dieselbe.

verwandte Informationen