我正在尝试使用可变参数创建宏,并对其进行迭代。最终结果应该是:
\foreach[x]((var = \x )){foo}{bar}{baz}\null
评估为
var = foo var = bar var = baz
我的天真猜测是这样的:
\def\Macro#1{\if \null#1 . \else ,\noexpand\Macro \fi}
\Macro foogg\null
我期望它评估为,,,,,.
,但它评估为,oogg
。我理解\noexpand
行为有误吗?
答案1
更改\noexpand
为\expandafter
,这就是你需要“跳过”的\fi
。同样,埃格尔指出,\if\null
不会起作用。要么使用\ifx
,要么更改\null
为\relax
,并希望它不包含在您的文本中。之所以\relax
会起作用,是因为它不可扩展并\if
接受它,而不是扩展。由于\relax
或\null
可能被其他人使用,更安全的选择是使用不存在的命令,例如\thisIStoheczSdelimiter
:
\def\Macro#1{\ifx\thisIStoheczSdelimiter#1 . \else ,\expandafter\Macro \fi}
\Macro foogg\thisIStoheczSdelimiter
至于工作foreach
周期,请查看pgffor
包。你的代码,如果我没记错的话,可以重写为
\foreach \x in {foo, bar, baz}{ var = \x, }
答案2
\def\Macro#1{\if \null#1 . \else ,\noexpand\Macro \fi}
\Macro foogg\null
\def\xnull{\null}
\def\Macro#1{\def\tmp{#1}\ifx\tmp\xnull\else ,#1\expandafter\Macro \fi}
\Macro foogg\null
\bye
,foogg
从原始版本生成,然后,f,o,o,g,g
从修改后的版本生成,在原始版本中,使其\noexpand
表现\Macro
得像\relax
,因此在第一次调用后不执行任何操作,因此只f
被视为参数。
以上是纯 TeX,但如果你打算将其用于 LaTeX,你应该使用不同的语法,LaTeX 的主要目的之一是提供统一的语法结构,LaTeX 命令绝不接受可变数量的{}
参数。LaTeX 语法是单个{}
参数内的逗号分隔列表。