定义 NewExpandableDocumentCommand,其名称位于宏中

定义 NewExpandableDocumentCommand,其名称位于宏中

如果宏或参数(比如#1)包含一些字符串,比如,我可以使用类似以下方法Mystring创建宏:\PrefixMystring{}{}

\expandafter\newcommand\csname Prefix#1\endcsname[2]{
  the arguments are ##1 and ##2
}

我想做一些类似的事情\NewExpandableDocumentCommand,正确的做法是什么?

\documentclass[]{article}

\begin{document}

%% \createNewAnimal{Cat}{Miaou} should create a new command \helloCat{Bob} outputting "Miaou Bob".
\NewDocumentCommand{\createNewAnimal}{mm}{
  %%% How can I do the same with NewExpandableDocumentCommand instead of newcommand?
  \expandafter\newcommand\csname hello#1\endcsname[1]{
    #2 ##1.
  }
}

\createNewAnimal{Cat}{Miaou}
\createNewAnimal{Dog}{Woooof}

\helloCat{Bob}
\helloDog{Alice}

\end{document}

编辑 哦,事实上,在我的测试中,上述方法失败了\NewExpandableDocumentCommand...但原因是我在参数周围添加了括号,例如:\expandafter\NewExpandableDocumentCommand{\csname zx#2\endcsname}{}{…}而不是\expandafter\NewExpandableDocumentCommand\csname zx#2\endcsname{}{…},这导致了错误:

ERROR: LaTeX cmd Error: First argument of '\NewExpandableDocumentCommand' must be a command

问题解决:

\documentclass[]{article}

\begin{document}

%% \createNewAnimal{Cat}{Miaou} should create a new command \helloCat{Bob} outputting "Miaou Bob".
\NewDocumentCommand{\createNewAnimal}{mm}{
  %%% How can I do the same with NewExpandableDocumentCommand instead of newcommand?
  \expandafter\NewDocumentCommand\csname hello#1\endcsname{m}{
    #2 ##1.
  }
}

\createNewAnimal{Cat}{Miaou}
\createNewAnimal{Dog}{Woooof}

\helloCat{Bob}
\helloDog{Alice}

\end{document}

答案1

我认为\ExpandArgs这是有可能的(但我不知道是否有更好的选择)。

\documentclass[]{article}

\begin{document}

%% \createNewAnimal{Cat}{Miaou} should create a new command \helloCat{Bob} outputting "Miaou Bob".
\NewDocumentCommand{\createNewAnimal}{mm}{%
  \ExpandArgs{c}\NewExpandableDocumentCommand{hello#1}{m}{#2 ##1.}%
}

\createNewAnimal{Cat}{Miaou}
\createNewAnimal{Dog}{Woooof}

\helloCat{Bob}
\helloDog{Alice}

\end{document}

答案2

我建议使用通用宏工厂。

\documentclass{article}

\ExplSyntaxOn

\NewDocumentCommand{\NewPrefixedDocumentCommand}{mmmm}
 {% #1 = prefix
  % #2 = added part
  % #3 = argument list
  % #4 = replacement text
  \tobiasbora_prefixed:Nnnnn \NewDocumentCommand { #1 } { #2 } { #3 } { #4 }
 }
\NewDocumentCommand{\NewPrefixedExpandableDocumentCommand}{mmmm}
 {% #1 = prefix
  % #2 = added part
  % #3 = argument list
  % #4 = replacement text
  \tobiasbora_prefixed:Nnnnn \NewExpandableDocumentCommand { #1 } { #2 } { #3 } { #4 }
 }

\cs_new_protected:Nn \tobiasbora_prefixed:Nnnnn
 {
  \exp_args:Nc #1 { #2 #3 } { #4 } { #5 }
 }

\ExplSyntaxOff

% test for the generic function
\NewPrefixedDocumentCommand{Prefix}{Test}{mm}{Do something with #1 and #2}

% test for your use case
\NewDocumentCommand{\createNewAnimal}{mm}{%
  \NewPrefixedDocumentCommand{hello}{#1}{m}{#2 ##1.}%
}

\createNewAnimal{Cat}{Miaou}
\createNewAnimal{Dog}{Woooof}

\begin{document}

\PrefixTest{A}{B}

\helloCat{Bob}
\helloDog{Alice}

\end{document}

在此处输入图片描述

在这些特殊情况下您可能还会使用\NewPrefixedExpandableDocumentCommand,但请小心:使用Expandable不会应用某种魔法使本来不可扩展的东西变得可扩展。

答案3

您可以简单地使用 TeX 原语来解决您的“动物问题”:

\def\createNewAnimal#1#2{\expandafter\def\csname hello#1\endcsname##1{#2 ##1}}

\createNewAnimal{Cat}{Miaou}
\createNewAnimal{Dog}{Woooof}

\helloCat{Bob}    % prints: Miaou Bob

\helloDog{Alice}  % prints: Woooof Alice

相关内容