我正在查看这个答案并试图理解代码,我是 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}
现在\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
)采用单个参数但丢弃它并扩展为“无”。
修复 catcodes
更棘手但也更有趣的是涉及 catcode 更改的情况。当 TeX 解析宏的参数时,它会在读取参数文本时修复 catcode。这对您来说无关紧要,因为这里没有 catcode 更改。但假设给出以下有点牵强的例子:
\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}}
这导致
3四5-3四5
345-3四5
前四行定义了一个全局宏4
,它扩展为four
。通常4
具有 catcode 12(其他),因此我们将其更改为 13(活动)以便能够将其制作成宏。\f
执行时,此处将这些宏带回范围。
执行时\exA
,的 catcode4
会更改为 13,之后会在以下两组中将4
其扩展为。这里根本没有参数,所以这很简单。four
另一方面,在\exB
宏中,第一{345}
部分\@firstofone
仅处理相同的文本,但修复了 catcode至4
12。一旦修复,就不能再更改了!即使 catcode 更改\f
已处理前第一个345
,不会对其产生任何影响。由于第二个的 catcode{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
最初在哪里读到过,但它可能是在其中一个上下文中。