我经常想定义一个命令(使用 xparse),如下所示
\NewDocumentCommand{\Comon}{oo}{
\IfNoValueTF{#1}{
\mathsf{Mod}
}{
\IfNoValueTF{#2}{
\mathsf{Mod}_{#1}
}{
\mathsf{Mod}_{#1}(#2)
}
}
}
\Mod
这样,具有不同数量可选参数的相同命令名将显示不同的结果。
理想情况下,我可以编写自己的命令\NewCommandAlts
,调用方式如下
\NewCommandAlts{\Mod}{2}
{\mathsf{Mod}}
{\mathsf{Mod}_{#1}}
{\mathsf{Mod}_{#1}(#2)}
并将定义一个\Mod
与上面定义的命令等效的命令。
我所拥有的最好的东西是
\newcommand{\NewCommandAltsTwo}[4]{
\NewDocumentCommand{#1}{oo}{
\IfNoValueTF{##1}{#2}{\IfNoValueTF{##2}{#3}{#4}}
}
}
\NewCommandAltsTwo{\Mod}
{\mathsf{Mod}}
{\mathsf{Mod}_{#1}}
{\mathsf{Mod}_{#1}(#2)}
有效。对于如何编写处理任意数量参数的案例,您有什么想法吗?
答案1
只要仅在前 (k-1) 个可选参数也被指定的情况下指定第 k 个可选参数,您就可以执行以下操作:
\newcommand\Firstoftwo[2]{#1}%
\newcommand\Secondoftwo[2]{#2}%
\newcommand\NewCommandAlts[2]{%
\ifcat$\detokenize\expandafter{\Firstoftwo#2{}{}}$\expandafter\Firstoftwo\else\expandafter\Secondoftwo\fi
{\NewDocumentCommand{#1}{}{}}%
{\NewCommandAltsReverseLoop{0}{#1}{}{}#2{}{}\NewCommandAlts{}}%
}%
\csname @ifdefinable\endcsname\NewCommandAltsReverseLoop{%
\long\def\NewCommandAltsReverseLoop#1#2#3#4#5#6\NewCommandAlts#7{%
%#1 amount of items processed so far.
%#2 command to define
%#3 o-collection
%#4 reversed list
%#5 this item
%#6 remaining items
%#7 array of argument-numbers.
\ifcat$\detokenize\expandafter{\Firstoftwo#6{}{}}$\expandafter\Firstoftwo\else\expandafter\Secondoftwo\fi
{%
\expandafter\NewCommandAltsLoop\expandafter{\Firstoftwo{}#3}{#2}{}#4{}{}\NewCommandAlts{0}#7\NewCommandAlts
}{%
\expandafter\NewCommandAltsReverseLoop\expandafter{\number\numexpr#1+1\relax}{#2}{#3o}{{#5}#4}#6\NewCommandAlts{{#1}#7}%
}%
}%
}%
\csname @ifdefinable\endcsname\NewCommandAltsLoop{%
\long\def\NewCommandAltsLoop#1#2#3#4#5\NewCommandAlts#6#7\NewCommandAlts{%
%#1 o-collection
%#2 command to define
%#3 result
%#4 this item
%#5 remaining items
%#6 this argument number
%#7 remaining argument-numbers
\ifcat$\detokenize{#5}$\expandafter\Firstoftwo\else\expandafter\Secondoftwo\fi
{%
\NewDocumentCommand{#2}{#1}{#3}%
}{%
\ifnum#6=0 \expandafter\Firstoftwo\else\expandafter\Secondoftwo\fi
{%
\NewCommandAltsLoop{#1}{#2}{#4#3}#5\NewCommandAlts#7\NewCommandAlts
}{%
\NewCommandAltsLoop{#1}{#2}{\IfNoValueTF{###6}{#4}{#3}}#5\NewCommandAlts#7\NewCommandAlts
}%
}%
}%
}%
\NewCommandAlts{\Mod}{%
{\mathsf{Mod}} % Tokens in case no optional arguments
{\mathsf{Mod}_{#1}} % Tokens in case one optional argument
{\mathsf{Mod}_{#1}(#2)} % Tokens in case two optional arguments
%{...} % Tokens in case three optional arguments
%{...} % Tokens in case four optional arguments
%{...} % Tokens in case five optional arguments
%{...} % Tokens in case six optional arguments
%{...} % Tokens in case seven optional arguments
%{...} % Tokens in case eight optional arguments
%{...} % Tokens in case nine optional arguments
}%
% \expandafter\show\csname Mod code\endcsname
% \ShowDocumentCommandArgSpec\Mod
\documentclass{article}
\begin{document}
$\Mod$
$\Mod[A]$
$\Mod[A][B]$
\end{document}