我正在尝试创建一个\dummy
用于动态宏定义的命令 ( )。它应该返回一个动态命名的宏 ( #3
),其内容在迭代#2
后连接起来。#1
\documentclass{scrartcl}
\usepackage{forloop}
\usepackage{xifthen}
\newcounter{loopcnt}
\makeatletter
\newcommand{\dummy}[3]{%
\edef\temp{#1}
%
\forloop[-1]{loopcnt}{#1}{\value{loopcnt} > 0}{%
\ifthenelse{\theloopcnt = \temp}{%
\edef\tempcmd{M}
}{%
\edef\tempcmd{M;\tempcmd}
}
}
\expandafter\def\csname #3 \endcsname{\tempcmd}
}
\makeatother
\begin{document}
\dummy{5}{M}{varSpec}
\csname varSpec \endcsname % This works - outputs "M;M;M;M;M"
\varSpec % This doesn't work
\end{document}
我很好奇为什么调用\csname varSpec \endcsname
after 可以按预期工作,而调用\varSpec
却不行?我该如何工作\varSpec
?
答案1
我建议用更简单的方法来完成这项工作:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\dummy}{mO{;}mm}
{
\cs_new:cpx { #4 }
{
\exp_not:n { #3 }
\prg_replicate:nn { #1 - 1 } { \exp_not:n { #2 #3 } }
}
}
\ExplSyntaxOff
\begin{document}
\dummy{5}{M}{varSpec}
\dummy{3}[\textit{\&}]{\textbf{a}}{varBf}
\varSpec % This doesn't work
\varBf
\end{document}
使用\cs_new:cpx
在尾随参数中指定的名称构建的命令,对 进行完全扩展\prg_replicate:nn
。但是,主要参数和分隔符受到保护,不会进行扩展,以防它们包含“危险”命令,如\textbf
示例中所示。
请注意,通过这种方法你甚至可以说
\dummy{\value{mycounter}}{x}{myCmd}
除了简单之外,另一个优点是,\ExplSyntaxOn
和之间的结束线被忽略\ExplSyntaxOff
当然,您也可以使用自己的代码来完成此操作:
\newcommand{\dummy}[3]{%
\forloop[-1]{loopcnt}{#1}{\value{loopcnt} > 0}{%
\ifthenelse{\value{loopcnt} = #1}{%
\edef\tempcmd{#2}%
}{%
\edef\tempcmd{#2;\tempcmd}%
}%
}%
\expandafter\let\csname #3\endcsname\tempcmd
}
请注意最后一行:使用您的代码,您将定义\varSpec
扩展为\tempcmd
,如果介入另一个调用,它将发生变化\dummy
。但\let
这种情况不会发生。
#3
此外,和之间不应有空格\endcsname
,否则它将成为宏名称的一部分。