# What is wrong with this macro-defining macro?

have this \newsetter macro that defines a "setter" macro (for lack of a better name) and a @-prefixed macro of the same name that holds the value. This is how is supposed to work:

\newsetter\macro

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

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


And this is the \newsetter code:

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


The problem with this code is that it only works in a particular order:

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

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


Whereas the following fails:

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

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


What is wrong here?

-

You have defined \firrstword (for example) as

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


which means that \firstword does not define \@firstword but a command based on whatever is the current value of \@temptokena. If you use a toks register you need to expand it earlier so \firstword is defined in terms of its value, or simpler do not use the toks register at all:

\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

-
Nice. I had used the token register to avoid processing the argument twice. – Ernest A Sep 22 '13 at 19:41