如何csname
正确扩展?在下面的 MWE 中,我尝试制作一个将\prefixator
和“绑定”在一起的宏\afterator
。我希望\giveme{im}
等同于\givemeim
。
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\makeatletter
\def\halo@re{Re}
\def\halo@im#1{Im}
\def\prefixator{halo@}
\newcommand{\giveme}{
\edef\vv{\csname\prefixator\afterator\endcsname}
\meaning\vv
}
\newcommand{\givemeim}{
\let\vv\halo@im
\meaning\vv
}
\makeatother
\begin{document}
\def\afterator{im} %\def\afterator{re} works as expected
\giveme
\end{document}
我知道\edef
这行不通,因为它试图扩展\halo@im
但没有参数。我尝试了所有方法,\let
但没有成功\giveme{re}
。
编辑:实际问题当\SetEnumitemKey{sth}{unknownlabel=\arabic{enumi}}
使用时会创建具有\enitkv@enumitem@sth
以下含义的宏:\enitkv@setkeys{enumitem}{unknownlabel=\arabic{enumi}}
。在这种情况下prefixator
是\enitkv@enumitem@
,并且afterator
是sth
。(上下文是邪恶的)
(有缺陷)MWE:
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{enumitem}
\makeatletter
\SetEnumitemKey{sth}{unknownlabel=\arabic{enumi}}
% -- can't touch these
\def\prefixator{enitkv@enumitem@}
\def\afterator{sth}
% --
\newcommand{\giveme}{
% make a macro \vv \enitkv@enumitem@sth (bind them)
% \let\vv\enitkv@enumitem@sth
\edef\vv{\csname\prefixator\afterator\endcsname{}}
\meaning\vv
}
\makeatother
\begin{document}
\giveme
\end{document}
答案1
你的\csname
...\endcsname
是正确的。你忽略的是,\edef
无论回报如何,它都会不断扩大\csname\prefixator\afterator\endcsname
,并且那是代码失败的时候。
经过一步扩展后,\csname\prefixator\afterator\endcsname
变成\halo@im
,然后剩下\edef\vv{\halo@im}
。再进行一次扩展,您会收到错误消息:
! Argument of \halo@im has an extra }.
<inserted text>
\par
l.24 \giveme
?
这说明 TeX 尝试获取的参数时\halo@im
发现的}
太早,从而导致了问题。您需要执行以下任一操作:A)从定义中删除参数\halo@im
(IE, \def\halo@im{Im}
,就像你做的那样\halo@re
),或者b)\halo@im
,在 中添加一个正式参数\edef
:\edef\vv{\csname\prefixator\afterator\endcsname{}}
。第一个选项更有意义,因为您没有#1
使用\halo@im
。
但是如果您只是想要一个不同名称的命令的副本,您可以执行以下操作:
\expandafter\let\expandafter\NewName\csname<command name>\endcsname
第一步扩展步骤是扩展第一个\expandafter
,然后跳过\let
并扩展第二个\expandafter
,而第二个又会跳过\NewName
并扩展\csname
(扩展 X,跳过 S):
% X S X S X
\expandafter\let\expandafter\NewName\csname<command name>\endcsname
一旦扩展\csname
结束,您将得到:
\let\NewName\<command name>
它可以满足您的要求。