自动生成新命令

自动生成新命令

为了将内容结构与风格分开,我决定实现表示随机变量的命令:

\newcommand{\myrv}[1]{\mathbf{#1}}
\newcommand{\rvA}{\myrv{A}}
\newcommand{\rvB}{\myrv{B}}
\newcommand{\rvC}{\myrv{C}}
...

这样,如果我决定将随机变量的样式从 改为\mathbf\mathbb我所需要做的就是更改 的定义\myrv。有没有办法自动生成命令\rvA\rvB\rvC、 ...?

答案1

还有其他类似的问题,但据我所知,没有一个问题明确地处理这个问题。

\documentclass{article}

\makeatletter
\newcommand{\generate}[4]{%
  %#1 = prefix, #2 = macro, #3 = starting point, #4 = end point
  \def\@tempa{#1} % we don't want to lowercase it
  \count@=`#3
  \loop
  \begingroup\lccode`?=\count@
  \lowercase{\endgroup\@namedef{\@tempa ?}{#2{?}}}%
  \ifnum\count@<`#4
  \advance\count@\@ne
  \repeat
}

\generate{rv}{\mathbf}{A}{Z}
\show\rvA
\show\rvZ
\generate{rv}{\mathbf}{a}{z}
\show\rva
\show\rvz

\show命令只是为了看看它是否有效。终端输出是

> \rvA=macro:
->\mathbf {A}.
l.17 \show\rvA

? 
> \rvZ=macro:
->\mathbf {Z}.
l.18 \show\rvZ

? 
> \rva=macro:
->\mathbf {a}.
l.20 \show\rva

? 
> \rvb=macro:
->\mathbf {b}.
l.21 \show\rvb

扩展版本使用expl3

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\generate}{ m m m m }
 {
  \iliketocode_generate:nnnn { #1 } { #2 } { #3 } { #4 }
 }

\cs_new_protected:Nn \iliketocode_generate:nnnn
 {
  \cs_set:Nn \__iliketocode_generate_name:n { #3 }
  \cs_set:Nn \__iliketocode_generate_wrapper:n { \exp_not:n { #4 } }
  \int_step_inline:nnnn { `#1 } { 1 } { `#2 }
   {
    \cs_new:cpx
     {
      \__iliketocode_generate_name:n { \char_generate:nn { ##1 } { 11 } }
     }
     {
      \exp_args:Nf \__iliketocode_generate_wrapper:n { \char_generate:nn { ##1 } { 11 } }
     }
   }
 }
\ExplSyntaxOff

\generate{A}{Z}{rv#1}{\mathbf{#1}}
\show\rvA
\show\rvZ
\generate{a}{z}{rv#1}{\mathbf{#1}}
\show\rva
\show\rvz
\generate{A}{Z}{#1cal}{\mathcal{#1}}
\show\Acal
\show\Zcal
\generate{A}{Z}{#1#1#1}{\mathrm{#1}}
\show\RRR
\show\PPP

的语法\generate有点不同:第一个参数是起点,第二个参数是终点;第三个参数是名称的格式,第四个参数是所需定义的格式,其中#1代表循环中的当前字母。

例子应该能表达清楚其含义。

这是终端上的输出,仅供检查。

> \rvA=\long macro:
->\mathbf {A}.

> \rvZ=\long macro:
->\mathbf {Z}.

> \rva=\long macro:
->\mathbf {a}.

> \rvz=\long macro:
->\mathbf {z}.

> \Acal=\long macro:
->\mathcal {A}.

> \Zcal=\long macro:
->\mathcal {Z}.

> \RRR=\long macro:
->\mathrm {R}.

> \PPP=\long macro:
->\mathrm {P}.

答案2

您可以定义一个宏,它采用名称列表并创建相应的宏:

\documentclass{article}

\newcommand{\myrv}[1]{\mathbf{#1}}

\makeatletter
\newcommand*\defrvar[1]{
  \expandafter\newcommand\csname rv#1\endcsname[1][]{\myrv{#1}}}

\newcommand*\defrvars[1]{
  \@for\@i:=#1\do{\expandafter\defrvar\expandafter{\@i}}}
\makeatother


\defrvars{a,b,c} % this defines \rva, \rvb and \rvc

\begin{document}

Hi $\rva, \rvb + \rvc$
\end{document}

答案3

\newcommand{\myrv}[1]{\mathbf{#1}}
\newcommand{\makerv}[1]{%
  \expandafter\newcommand\csname rv#1\endcsname{\myrv{#1}}%
}

\newcommand{\defAllRv}[1]{%
  \ifx#1\deffAllRv%
  \else%
      \makerv{#1}\expandafter\mydefallb%
  \fi}
\deffAllRv abcdefghijklmnopqrstuvwxyz\defAllRv

此代码定义所有 \rva...\rvz。它基于: \if 和 \ifx 之间的区别在另一个新命令中定义一个带有变量名的新命令

相关内容