为了将内容结构与风格分开,我决定实现表示随机变量的命令:
\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 之间的区别和 在另一个新命令中定义一个带有变量名的新命令