
我正在查看這個答案並試圖理解程式碼,我是 LaTeX 的超級新手(我的第二天),我堅持了程式碼的以下部分,我無法使其在非表格環境中工作。這是我不明白的最簡單的形式。
\documentclass{article}
\begin{document}
\newcommand*\f[3]{#1-#2-#3}
\newcommand*\ex[1]{\f#1 - \expandafter\f\@firstofone}
Try \ex{111}{221}
\end{document}
由於某種原因,我不清楚,在連結的程式碼中,最後一個參數沒有被消耗,但它被構造所消耗expandafter\f\...
。根據我的理解,\expandafter
應該首先“運行” \@firstofone
,獲取{221}
參數,去掉括號並將其輸入到\f
.這不會發生,我不明白為什麼。
答案1
您需要使用\makeatletter
它才能工作,但這是最少的。
呼叫\ex{111}{221}
首先擴展為
\f 111 - \expandafter\f\@firstofone{221}
Now\f
被展開,它會尋找三個參數,尋找1
、1
和1
,因為如果缺少大括號,TeX 將使用單一標記。
根據定義,\f
它被擴展並且替換文字被重新插入到輸入流中:
1-1-1 - \expandafter\f\@firstofone{221}
代幣1-1-1 -
不可擴展,因此它們被發送到下一階段。現在還剩下
\expandafter\f\@firstofone{221}
這將預留\f
並展開\@firstofone
,僅返回其(無括號參數),所以我們得到
\f221
那就變成了2-2-1
。因此,您的程式碼的最終效果是列印
1-1-1 - 2-2-1
這似乎不太有用。無論你在哪裡發現它,都不要相信它。
答案2
正如egreg在他的回答中指出的那樣\@firstofone
不是很有用,在這種特殊情況下沒有什麼區別。然而,也有這樣的情況是有用。為了完整起見,我想舉兩個例子。
可擴充宏
在為什麼\expandafter\@firstoftwo
成語?給出了完全可擴展巨集的典型用例\@firstoftwo
。,一種 LaTeX 的“恆等函數”,在僅應處理單一參數的類似上下文中很有用:\@secondoftwo
\@firstofone
\def\gobbleIfZero#1{%
\ifnum#1=0
\expandafter\@gobble
\else
\expandafter\@firstofone
\fi
}
foo\gobbleIfZero{0}{bar}
foo\gobbleIfZero{123}{bar}
會給
富
富巴
\@gobble
(如\@firstofone
)採用單一參數,但將其丟棄並擴展為“無”。
修復目錄程式碼
更棘手但也更有趣的是涉及catcode更改的情況。當 TeX 解析巨集的參數時,它會在讀取參數文字時修復catcodes。這對於您的情況並不重要,因為這裡沒有目錄程式碼變更。但假設給了以下一些人為的例子:
\begingroup
\catcode`4=\active
\gdef 4{four}
\endgroup
\newcommand*\f{\catcode`4=\active}
\newcommand*\exA{\f}
\newcommand*\exB{\expandafter\f\@firstofone}
{\exA{345}--{345}}
{\exB{345}--{345}}
這導致
3four5-3four5
345-3四5
前四行定義了一個4
擴展為 的全域巨集four
。通常4
有catcode 12(其他),因此我們將其更改為13(活動)以便能夠從中建立巨集。\f
執行時,此處將此巨集帶回作用域。
執行時\exA
,catcode4
改為 13,隨後使其4
擴展到four
以下兩組。這裡根本沒有參數,所以這很簡單。
另一方面,在\exB
巨集中,第一{345}
部分由\@firstofone
僅傳回相同的文本,但修復了catcode到4
12.一旦確定,就不能再更改了!即使catcode從\f
已處理前第一個345
,不會對其產生任何影響。由於第二組的目錄程式碼{345}
尚未修復,因此變更仍將適用於該群組。
如果您想將額外的程式碼注入處理 catcode 變更的現有巨集中,此行為會非常方便,例如\verb
(靈感來自這顆 TeX 珍珠):
\begingroup
\catcode`\/\active
\catcode`\_\active
\@firstofone{%
\verb|%
\catcode`\/\active \def/{\par}%
\catcode`\_\active \def_#1_{\textcolor{blue}{#1}}%
}_\documentclass_{article}/_\begin_{document}/ We all love _\LaTeX_!/_\end_{document}|
\endgroup
哪個輸出
我不知道你\@firstofone
首先在哪裡讀到的,但它可能是在其中一個上下文中。