\edef
进行扩展,但不执行命令。以下示例中如何使在其调用时而不是在定义时\foo
执行 的赋值?为什么会产生而不是?使用 可根据需要工作。此外,调用会产生。为什么?\tmp
\foo
0F
1F
\let
\bar
\baz
TeX capacity exceeded
\def\foo{F}
\def\bar{B}
\def\baz{Z}
\newcount\tmp
\newcount\N
\edef\foo{\tmp = \if aa \N \fi \the\tmp \foo}
\N=1
\foo
\let\oldbar = \bar
\def\bar{\tmp = \if aa \N \fi \the\tmp \oldbar}
\N=2
\bar
\expandafter\def\expandafter\baz\expandafter{\tmp = \if aa \N \fi \the\tmp \baz}
\N=3
%\baz
\bye
答案1
\foo
如果您希望在替换文本的开头添加一些内容来增强其定义,则方法非常标准:
\def\leftadd#1#2{% #1 is a parameterless macro, #2 a token list
\toks0=\expandafter{#1}% store the expansion of #1
\toks2={#2}% store the token list
\edef#1{\the\toks2 \the\toks0}% redefine #1
}
已经提出了几种其他方法,这可能是最容易理解的。它基于 传递的标记\the<toks register>
在 中不再扩展的规则\edef
。
使用 e-TeX 扩展可以省去令牌寄存器:
\def\leftadd#1#2{\edef#1{\unexpanded{#2}\unexpanded\expandafter{#1}}}
现在
\def\foo{F}
\leftadd\foo{\tmp = \if aa \N \fi \the\tmp}
相当于定义\foo
为
\def\foo{\tmp = \if aa \N \fi \the\tmp F}
首先。
令牌注册免费版本:
\def\leftadd#1#2{\expandafter\leftaddaux\expandafter{#1}{#2}{#1}}
\def\leftaddaux#1#2#3{\def#3{#2#1}}
答案2
编辑后,这解决了 OP 提出的所有问题,关于\foo
和\baz
。它还解决了 OP 在评论中提出的后续问题。
通过在定义中\foo
放置前置\noexpand
的来修复。并且,响应 OP 的评论,如果必须前置,则没有问题,如 MWE 中所示。\the\tmp
\foo
\tmp
修复涉及在新定义中设置结果之前\baz
一直扩展到。我放了一堆东西来简化这个过程。还编辑了以作为解决方案的一部分进行演示。\baz
\baz
\glob
\advance\tmp
\baz
重新编辑以解决 OP 在评论中提出的其他情况:
\painful
类似于\baz
,但不使用\glob
。
\superbaz
\tmp
同时演示了之前值和之后值的使用。
\documentclass{article}
\begin{document}
\def\foo{F}
\def\bar{B}
\def\painful{W}
\def\baz{Z}
\newcount\tmp
\newcount\N
\edef\foo{\tmp = \if aa \N \fi \advance\tmp by 7 \noexpand\the\tmp \foo}
\N=1
\foo
\let\oldbar = \bar
\def\bar{\tmp = \if aa \N \fi \the\tmp \oldbar}
\N=2
\bar
\def\glob{\tmp = \if aa \N \fi \advance\tmp by 2\noexpand\the\tmp}
\expandafter\def\expandafter\baz\expandafter{\expandafter\glob\baz}
\N=3
\baz
\expandafter\def\expandafter\painful\expandafter{\expandafter\tmp%
\expandafter\expandafter\if\expandafter a\expandafter a%
\expandafter\N\expandafter\fi\expandafter\the\expandafter\tmp\painful}
\N=4
\painful
\verb+\tmp+ is currently \the\tmp
\edef\superbaz{\the\tmp Z}
\def\glob{\tmp = \if aa \N \fi \advance\tmp by 2\noexpand\the\tmp}
\expandafter\def\expandafter\superbaz\expandafter{\expandafter\glob\superbaz}
\N=5
\superbaz
%\bye
\end{document}
最后附录:
回答 OP 评论How to leave \the\tmp only in \superbaz and remove from \def\glob? (so that only 7Z will be printed). Also, how to do the same without \def\glob?
鞭打一匹死马……
\documentclass{article}
\begin{document}
\newcount\tmp
\newcount\N
\def\ultimatebaz{\the\tmp Z}
\expandafter\def\expandafter\ultimatebaz\expandafter{%
\expandafter\tmp\expandafter\expandafter\if\expandafter a\expandafter a%
\expandafter\N\expandafter\fi\expandafter\advance\expandafter\tmp%
\expandafter b\expandafter y\expandafter 2\expandafter\noexpand\ultimatebaz}
\N=5
\ultimatebaz\par
\end{document}