理解 \@firstofone

理解 \@firstofone

我正在查看这个答案并试图理解代码,我是 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展开并寻找三个参数,找到111,因为如果缺少括号,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仅处理相同的文本,但修复了 catcode412。一旦修复,就不能再更改了!即使 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最初在哪里读到过,但它可能是在其中一个上下文中。

相关内容