变量名 \newcommand 带有另一个 \newcommand 中的参数

变量名 \newcommand 带有另一个 \newcommand 中的参数

“在另一个新命令中定义一个带有变量名的新命令”我们学习了如何\newcommand在命令定义中使用另一个命令\newcommand,当内部命令的名称需要包含外部命令的参数时。现在,假设我想做同样的事情,但内部命令\newcommand也需要参数,即我希望以下代码能够工作:

\newcommand{\defsilly}[1]{%
  % define a command named silly#1 , taking a single parameter
}
\defsilly{willy}
\sillywilly{theparameter}

动机:我正在编写一个论文文档类,其中包含一堆以下类型的命令对:

\newcommand{\iitthesis@authorEnglish}{Name of Author}
\newcommand{\authorEnglish}[1]{\renewcommand{\iitthesis@authorEnglish}{#1}}

我想用类似以下内容替换其中的每一对:

\iitthesis@thesisdatafield{authorEnglish}{Name of Author}

这定义了上述两个命令。

答案1

\newcommand{\iitthesis@thesisdatafield}[2]{%
  \@namedef{iitthesis@#1}{#2}}

\iitthesis@thesisdatafield{authorEnglish}{Name of Author}

您将定义\iitthesis@authorEnglish扩展为“作者姓名”,也就是说,您将发布相当于

\def\iitthesis@authorEnglish{Name of Author}

这不会检查定义的命令是否之前未定义。如果您也想进行此检查,请执行

\newcommand{\iitthesis@thesisdatafield}[2]{%
  \expandafter\@ifdefinable\csname iitthesis@#1\endcsname
    {\@namedef{iitthesis@#1}{#2}}}

但对于内部命令来说,通常不会这样做。

根据您的动机,我认为没有必要使用参数定义新命令。如果您还需要定义用户级命令,则可以使用相同的技术:

\newcommand{\iitthesis@thesisdatafield}[1]{%
  \long\@namedef{#1}##1{\@namedef{iitthesis@#1}{##1}}}

在这种情况下说

\iitthesis@thesisdatafield{authorEnglish}

将定义命令\authorEnglish,以便如果用户输入

\authorEnglish{A. U. Thor}

效果就像

\def\iitthesis@authorEnglish{A. U. Thor}

\long导致要执行的前缀\@namedef,因此\long\def参数可以跨越一个或多个段落。

LaTeX 内核采用了这种技术,实际上\author{A. U. Thor}定义了\@author最终扩展为“AU Thor”。

答案2

与另一个问题一样,您需要使用\csname .. \endcsname来构建宏名称,并将\expandafter其扩展为该名称,然后才能使用\newcommand(或类似方式) 定义该宏。只需在 后附加可选参数参数即可\endcsname

\newcommand{\iitthesis@thesisdatafield}[2]{%
   \expandafter\newcommand\csname iitthesis@#1\endcsname{#2}%
   \expandafter\newcommand\csname #1\endcsname[1]{\expandafter\renewcommand\csname iitthesis@#1\endcsname{##1}}%
}

请注意,您需要将#内部宏中的参数加倍,以便清楚它不是外部宏的第一个参数。

有一个\@namedef{<name>}<parameter text>{<macro code>}宏的作用基本相同,但使用的是 TeX 原语\def,而不是 LaTeX 的\newcommand。基本区别在于它不检查宏是否存在,而是在任何情况下都定义它,并且您必须以纯文本形式列出参数:#1而不是[1]#1#2而不是[2]等等。

相关内容