
I have created a command which creates another command. The parameter of the first command is a variable which is used in the second command. I would like the second command returns the value of the variable at the creation of the command.

\newcommand\testcom[2]{
\texttt{newcommand #1 : #2}
\expandafter\newcommand\csname#1\endcsname{#2}
}

\def \test{1} % set 1 to variable 'test'
\testcom{foofoo}{\test} % create command 'foofoo' and display "newcommand foofoo:1"

\def \test{2} % set 2 to variable 'test'
\testcom{barfoo}{\test} % create command 'barfoo' and display "newcommand barfoo:2"

\def \test{3} % set 3 to variable 'test'

\foofoo % display '3', excepted '1'

\barfoo % display '3', excepted '2'

\barfoo % display '3', excepted '2'



Next, I have modified the command to set an intermediate variable with \edef.

\newcommand\testcom[2]{
\texttt{newcommand #1 : #2}
\expandafter\edef\csname test@#1 \endcsname{#2}
\expandafter\newcommand\csname#1\endcsname{\csname test@#1 \endcsname}
}


Now, it creates a variable \test@barfoo with the value 2 and the command \barfoo returns this variable.


• if the argument is \test defined to be 3 you want to define your command to 3, but what do you want if the argument is not expandable \sqrt[2]{4} for example? Jun 1 at 14:57

Since both \foofoo and \barfoo are just defined to be \test, they will change their output if you change \test (as you've demonstrated). Also, there's no need to create an intermediate \test@<cmd>. You can just expand the argument using \edef:

\documentclass{article}

\newcommand\testcom[2]{%
\texttt{newcommand #1 : #2}%
\expandafter\edef\csname#1\endcsname{#2}%
}

\begin{document}

\def\test{1} % set 1 to variable 'test'
\testcom{foofoo}{\test} % create command 'foofoo' and display "newcommand foofoo:1"

\def\test{2} % set 2 to variable 'test'
\testcom{barfoo}{\test} % create command 'barfoo' and display "newcommand barfoo:2"

\def\test{3} % set 3 to variable 'test'

\ttfamily
\string\foofoo: \foofoo % display '1', excepted '1'

\string\barfoo: \barfoo % display '2', excepted '2'

\end{document}

• Ulrich Diez tends to increase confusion of beginners by mentioning too many subtle details at once.Despite this things might be clearer by mentioning that Werner's approach with \edef is focused on obtaining the "total expansion" of \test as definition-text of the macro to be defined via \testcom while U's approach is focused on "toplevel expansion" only. I.e., U's approach just expands \test and from the resulting tokens defines the macro while with Werner's approach expandable tokens coming from expanding (expandable tokens coming from expanding [etc]) \test get expanded also. Jun 3 at 13:21

As you did not yet answer the question in David Carlisle's comment I assume that as \testcom's second argument you always provide a single expandable token (an argumentless macro serving as "variable") and you always wish a macro, whose name is provided in \testcom's first argument, to be defined from the toplevel-expansion of that token:

\documentclass{article}
\newcommand\testcom[2]{%
\texttt{newcommand #1 : \detokenize\expandafter{#2}}%
\expandafter\newcommand\expandafter*\csname#1\expandafter\endcsname\expandafter{#2}%
}
\begin{document}
\def \test{1} % set 1 to variable 'test'
\testcom{foofoo}{\test} % create command 'foofoo' and display "newcommand foofoo : 1"

\def \test{2} % set 2 to variable 'test'
\testcom{barfoo}{\test} % create command 'barfoo' and display "newcommand barfoo : 2"

\def\woozle{X}%
\def \test{\woozle}
\testcom{barbar}{\test} % create command 'barbar' and display "newcommand barbar : \woozle"

\def \test{3} % set 3 to variable 'test'

\ttfamily

\string\foofoo=\meaning\foofoo % display '1', excepted '1'

\string\barfoo=\meaning\barfoo % display '2', excepted '2'

\string\barbar=\meaning\barbar % display '\woozle', excepted '\woozle'
\end{document}