如果在使用宏参数创建宏名时不使用 \detokenize,会发生什么问题?

如果在使用宏参数创建宏名时不使用 \detokenize,会发生什么问题?

我曾与一个 LaTeX 包的作者通信,在其中我自愿提供了类似如下的代码(我已将其匿名化,因此不清楚是哪个包):

\makeatletter
\newcommand{\savemacrostatewithname}[1]{%
    \expandafter\let%
        \csname saved@macro@state@named@#1\endcsname%
        \package@internal@macro%
}
\newcommand{\restoremacrostatewithname}[1]{%
    \ifcsname saved@macro@state@named@#1\endcsname%
    \else%
        \errmessage{Saved macro state named "#1" doesn't exist}%
    \fi%
    \expandafter\let%
        \expandafter\package@internal@macro%
        \csname saved@macro@state@named@#1\endcsname%
}
\makeatother

他们在回复中说而不是写作 #1 在你的宏中,你应该写 \detokenize{#1}因为它更安全。为什么这样更安全?如果我不这样做会有什么问题?

答案1

如果你有

\catcode`\!=\active
\def!{\hspace{2in} \fbox{boo} \hspace{2in}}

然后\csname foo!\endcsname会出现错误,因为名称不会扩展为字符标记序列,但与名称\csname\detokenize{foo!}\endcsname 相同\csname foo\string!\endcsname 并生成标记foo!

相关内容