LaTeX 巨集中的循環引用

LaTeX 巨集中的循環引用

在嘗試學習 LaTeX 中的巨集時,我遇到了這個定義:

\x@protect是一個帶有一個參數的宏,用「#1」表示。\@typeset@protect也被定義為\relax,因此執行第一個分支\ifx,它不執行任何操作。 (\ifx比較兩個巨集的意義。)因此 的唯一結果是它的參數,即 定義中的\x@protect第一個「 」被丟棄。這留下了命令 \protect (這是一個無操作)及其本身。這似乎是一個循環定義。事實上,事實並非如此。這是 LaTeX 作者試圖掩蓋自己蹤跡的卑鄙伎倆。再仔細看看 的列表,非常可疑。最後一個「 」和句點之間有兩個空格,而其他清單中最後一個控制序列之後只有一個!事實上,所有清單中只有一個尾隨空格。清單中的最後一個空格是其最後一個控制序列名稱的一部分,即“ ”,包括空格!\\\\\\\\\\\\\\

為什麼要循環引用?

為什麼遇到循環引用時它不會崩潰?

答案1

讓我們開始一個互動式會話pdflatex test,其中test.tex

\documentclass{article}

\DeclareRobustCommand{\?}{js bibra}

\makeatletter

\show\?

\show命令將停止運行,因此我們可以發出更多命令

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\?

\?處理時會發生什麼事?有兩種情況:如果與(which is )\protect的意思不同,則遵循錯誤分支。因此輸入流將有\@typeset@protect\relax

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

的擴展\@x@protect將刪除最後兩個標記,留下\protect\?\fi(並\fi最終消失)。

例如,當被賦予與 不同的意義時,\protected@edef就會發生這種情況。\protected@write\protect\@typeset@protect

如果有,則條件為 true,因此輸入流在跳過 false 分支後將具有:

\protect\?

現在\protect消失了,我們似乎和以前一樣在同一個地方。但我們不是,因為下面的標記\protect不同的由此\?被輸入到測試文檔中。

仔細查看第一個命令的輸出\show。我們得到

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

->和 尾隨句點之間,TeX 表示巨集的替換文字。這種表示法的規則是控製字後面接空格,而控制符號則不然。這解釋了後面的空格\x@protect以及\protect後面沒有空格\?。但尾隨期間之前是空格!他們來自哪裡?

當你這樣做時\DeclareRobustCommand{\?}{js bibra},LaTeX 會做幾件事,主要的事情是

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

然後使用這個巨集和一個非常不標準的名稱來定義 的「使用者級版本」\?。請注意 之前的空格\endcsname,它以巨集名稱結尾。

還有一些更多細節,但其想法是為了簡化輔助文件的編寫。在舊版的 LaTeX 中,我們看到類似的東西

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

當 LaTeX2e 發佈時,先前的程式碼變成了

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

利用新的抽象層次。在舊版本中,\LaTeX{}在章節標題中會寫

\protect\pLaTeX {}

在輔助文件中。現在它寫出

\LaTeX  {}

因為名稱和規則中的尾隨空格。讀入輔助檔案時,雙倍空格將被忽略。

\\對於諸如或 之類的控制符號來說,它略有不同\?,但總體思路是相同的。

相關內容