命令的作用相当于“\csname cmd \endcsname”,但不能相当于“\cmd”

命令的作用相当于“\csname cmd \endcsname”,但不能相当于“\cmd”

我正在尝试创建一个\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 \endcsnameafter 可以按预期工作,而调用\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,否则它将成为宏名称的一部分。

相关内容