# 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