如果我有以下一段代码,那么一切都会编译:
\documentclass{article}
\newcommand{\mycmd}{
\edef\tmpcmd{test} % No commands with arguments
\tmpcmd
}
\begin{document}
\mycmd
\end{document}
但如果它看起来像这样:
\documentclass{article}
\newcommand{\mycmd}{
\edef\tmpcmd{\textit{test}} % Has a command with argument
\tmpcmd
}
\begin{document}
\mycmd
\end{document}
然后我收到一个奇怪的错误:
! Undefined control sequence.
\GenericError ...
#4 \errhelp \@err@ ...
l.9 \mycmd
为什么是这样?
答案1
这个问题不是宏有参数,而是参数是否可扩展。例如,对 MWE 进行这样的轻微改动可以正常工作,因为\foo
是可扩展的:
\documentclass{article}
\newcommand{\mycmd}{%
\edef\tmpcmd{\foo{test}}% Has a command with argument
\tmpcmd
}
\newcommand\foo[1]{foo:#1:bar}
\begin{document}
\mycmd
\end{document}
OP 的 MWE 的问题在于它\textit
不是完全可扩展的。
宏\protected@edef
可以帮助人们解决许多这样的情况,而约瑟夫在对 OP 的评论中提到的链接(为了方便起见,我在这里重复一下)详细地解释了所有原因。
\documentclass{article}
\makeatletter
\newcommand{\mycmd}{%
\protected@edef\tmpcmd{\textit{test}}% Has a command with argument
\tmpcmd
}
\makeatother
\begin{document}
\mycmd
\end{document}
除了在这个网站上搜索“可扩展”之外,研究“脆弱”和“坚固”的概念也会很有启发,正如古斯塔沃所说。
答案2
\protected@edef
(参见 Steven 的回答),但不会禁止未声明为健壮的命令的扩展,除非您\protect
在替换文本中明确指定它们。以下是简单的替代方案
\documentclass{article}
\newcommand*{\mycmd}{%
\edef\tmpcmd{\noexpand\textit{test}}%
\tmpcmd
}
\begin{document}
\mycmd
\end{document}
更加通用,可能更加简洁,并且还有节省极少量内存的额外优势。