我创建了一个命令,该命令会创建另一个命令。第一个命令的参数是第二个命令中使用的变量。我希望第二个命令在创建命令时返回变量的值。
\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'
我理解命令\testcom{barfoo}{\test}
执行\newcommand\barfoo{\test}
但我已经接受\newcommand\barfoo{3}
。
接下来,我修改了命令以使用来设置中间变量\edef
。
\newcommand\testcom[2]{
\texttt{newcommand #1 : #2}
\expandafter\edef\csname test@#1 \endcsname{#2}
\expandafter\newcommand\csname#1\endcsname{\csname test@#1 \endcsname}
}
现在,它创建一个\test@barfoo
具有该值的变量2
,并且命令\barfoo
返回该变量。
我想知道是否存在最智能的方法。在我的上下文中,第二种方法newcommand
更复杂,\expandafter\edef\csname#1\endcsname{#2}
不足以取代newcommand
。
答案1
由于和都\foofoo
定义\barfoo
为\test
,因此如果您更改,它们的输出也会改变\test
(如您所演示的那样)。此外,无需创建中间的\test@<cmd>
。您只需使用扩展参数即可\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}
答案2
由于你还没有回答 David Carlisle 评论中的问题,我假设作为\testcom
第二个论点,你总是提供一个单个可扩展令牌(一个无参数的宏作为“变量”),并且你总是希望一个宏,它的名字在\testcom
第一个参数中提供,从中定义顶层扩展该令牌:
\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}