为什么如果 \edef 的参数是一个带参数的命令,它会产生错误?

为什么如果 \edef 的参数是一个带参数的命令,它会产生错误?

如果我有以下一段代码,那么一切都会编译:

\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 的评论中提到的链接(为了方便起见,我在这里重复一下)详细地解释了所有原因。

最小 \protected@edef 示例

脆弱命令和坚固命令之间有什么区别?

\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}

更加通用,可能更加简洁,并且还有节省极少量内存的额外优势。

相关内容