几天来,我一直在断断续续地思考以下问题。我想将宏中定义的选项与静态定义的选项一起插入到另一个宏的选项列表中。我似乎可以做到这一点,前提是我的宏是宏列表中的第一个“选项”(类似于使用宏传递到 \geometry{} 选项 - keyval 错误);但如果我尝试将其作为第二个选项传递,它不起作用。我很困惑为什么会这样。
展示有效方法的示例代码:
\def\opts{align=left,minimum width=10em}
\begin{tikzpicture}
\expandafter\node\expandafter[\opts,draw=none] at (0,0) {
Some fancy text.
};
\end{tikzpicture}
然而,这是行不通的:
\def\opts{align=left,minimum width=10em}
\begin{tikzpicture}
\expandafter\node\expandafter[draw=none,\opts] at (0,0) {
Some fancy text.
};
\end{tikzpicture}
这显然是有原因的;但我就是不明白。我认为这可能与 \expandafter 的工作方式有关。有人能给我解释一下吗?
答案1
\expandafter
读取其后的两个标记,将第一个标记放在一边,然后导致一第二个标记的级别扩展;然后像往常一样评估第一个标记,就好像第二个标记的扩展从一开始就存在一样。
因此你的
\expandafter\node\expandafter[\opts,draw=none]
扩展,\opts
因为第二个\expandafter
借助第一个而扩展。相反,
\expandafter\node\expandafter[draw=none,\opts]
无法到达\opts
,因为第二个后面的两个令牌\expandafter
是[
和d
。你需要一个不同的策略,因为
\expandafter\node\expandafter[\expandafter d\expandafter r\expandafter a\expandafter w\expandafter =\expandafter n\expandafter o\expandafter n\expandafter e\expandafter ,\opts]
似乎不是一个可行的选择。;-)
您可以做的是调用“全局”一级扩展:
\begingroup\edef\x{\endgroup
\noexpand\node[draw=none,\unexpanded\expandafter{\opts}]}\x
临时宏\x
在扩展后就会被遗忘,因为其扩展中的第一个标记是\endgroup
;由于,\node
它将保持不变,而将被扩展一次,并且由于 ,生成的标记列表将不会进一步扩展。\edef
\noexpand
\opts
\expandafter
\unexpanded
没有\unexpanded\expandafter{\opts}
,但只是\opts
危险的,如果\opts
包含宏,如\bfseries
;在任何情况下,你都希望它的一个级别扩张,而不是“全线扩张”。
答案2
假设(最有可能的情况)你的选项只是纯文本,并且\edef
可以安全地执行
\edef\tmp{\noexpand\node[draw=none,\opts] at (0,0)}\tmp
as\edef
将扩展其参数中的所有标记 (\node
被阻止扩展,因此当\tmp
扩展时,其扩展将是
\node[draw=none,align=left,minimum width=10em] at (0,0)
如果\opts
确实有无法以这种方式完全展开的令牌,则替代方案是
\def\tmp{\node[draw=none,}
\expandafter\tmp\opts] at (0,0)
然后\opts
只会被展开一次,\expandafter
而不是在中完全展开\edef
。