这个宏定义宏有什么问题?

这个宏定义宏有什么问题?

有这个\newsetter宏,它定义了一个“setter”宏(因为没有更好的名字)和一个同名的 @ 前缀宏,用于保存值。它应该这样工作:

\newsetter\macro

\macro{foo}
\@macro     % expands to foo

\macro{bar}
\@macro     % expands to bar

代码如下\newsetter

\newcommand\newsetter[1]{%
  \@temptokena=\expandafter{\expandafter\@gobble\string #1}% 
  \expandafter\newcommand\csname @\the\@temptokena\endcsname{}%
  \expandafter\newcommand\csname\the\@temptokena\endcsname[1]{%
    \expandafter\renewcommand\csname @\the\@temptokena\endcsname{##1}}}%

此代码的问题在于它只能按特定顺序起作用:

\newsetter\firstword
\firstword{Hello}
\newsetter\secondword
\secondword{World}

\@firstword\ \@secondword         % expands to Hello World

而以下操作失败:

\newsetter\firstword
\newsetter\secondword
\firstword{Hello}
\secondword{World}

\@firstword\ \@secondword         % expands to World, \@firstword is empty

这里有什么问题?

答案1

您已定义\firrstword(例如)为

> \firstword=\long macro:
#1->\expandafter \renewcommand \csname @\the \@temptokena \endcsname {#1}.
l.12 \show\firstword

这意味着\firstword并不定义\@firstword而是基于 的当前值的命令\@temptokena。如果你使用 toks 寄存器,则需要提前扩展它,以便\firstword根据其值进行定义,或者更简单地根本不使用 toks 寄存器:

\makeatletter

\newcommand\newsetter[1]{%
  \@temptokena=\expandafter{}% 
  \expandafter\newcommand\csname @\expandafter\@gobble\string #1\endcsname{}%
  \expandafter\newcommand\csname\expandafter\@gobble\string #1\endcsname[1]{%
    \expandafter\renewcommand\csname @\expandafter\@gobble\string #1\endcsname{##1}}}%

\newsetter\firstword
\newsetter\secondword
\firstword{Hello}

\secondword{World}

\show\@firstword
\show\@secondword

\stop

相关内容