答案1
这里的想法是\edef
使用宏(\x
)进行扩展,我们不想在“其他地方”更改:你永远不知道还有谁可能在使用\x
。因此,需要在组内定义\x
。然后,目标是获得组外部的结果,\edef
而不对其包含的标记数量做任何假设。\begingroup
和\endgroup
原语不可扩展,因此
\edef\x{%
\endgroup
<tokens>%
}
定义\x
为
> \x=macro:
->\endgroup <expansion of tokens> .
那么,“魔法”构造的结束就是\x
:
\begingroup
\edef\x{%
\endgroup
....
}\x
这会将 的定义插入\x
到输入流中。 的第一个标记是\endgroup
,因此它将在扩展的标记之前恢复 的先前定义\x
。 因此最终结果是执行扩展而不产生\x
任何影响。 (\x
这里“传统上”使用 ,但任何宏名称当然都可以。)
答案2
用法通常是\begingroup\edef\x{\endgroup<code>}\x
。这会完全扩展<code>
(通常使用 保护某些部分\noexpand
)然后对其进行处理。\begingroup
和\endgroup
保留 的定义\x
本地化,即 之后 的先前定义\x
仍然有效。因此\x
仅用作临时存储。
答案3
如果你有类似的东西
\def\XXX#1#2{%
\begingroup
% replace with some other important local code
\global#2=#1
\endgroup
}
然后\XXX{1.1pt}\bar
将全局设置\bar
为 1.1pt 的值。有时在当前组内设置值而不是全局设置更有意义,但其他一些代码仍然需要位于更深的组中,那么您可以这样做
\def\YYY#1#2{%
\begingroup
% replace with some other important local code
\edef\x{\endgroup\noexpand#2\number#1}\x
}
现在\YYY{1.1pt}\bar
将设置\bar
不是全局值为 1.1pt,% replace with some other important local code
部分仍为局部值。