LaTeX 允许使用可选参数。有时人们想改写通过使某些参数成为可选参数来执行命令:
\newcommand{\foo}[2]{
#some commands
}
到:
\newcommand{\foo}[2][a]{
#some commands
}
据我所知,LaTeX 不支持重载,因此无法以低耦合度实现某些参数的可选化,因为对方法的调用\foo{a}{b}
必须转换为\foo[a]{b}
。无法定义辅助方法\foo{}{}
以使包向后兼容。
我想知道有哪些工具可以自动重写命令调用,或者宏来优雅地解决这个问题。
答案1
我不确定我是否理解了你的问题。恕我直言,你想写
\foo {a}{b} ... % The macro \foo with two parameters will be invoked
\foo {a} ... % Another variant of the macro \foo with one parameter.
% May be the missing parameter is substituted by default here
不幸的是,我的解决方案不可扩展。扫描括号的处理是在主处理器级别完成的。但你可以定义 \foo 的变体,从零到九个参数:
% NormalTeXsyntaxOn
\long\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
\def\sdef#1{\expandafter\def\csname#1\endcsname}
\newcount\tmpnum
\def\foo{\def\fooC{}\tmpnum=0\futurelet\next\fooA}
\def\fooA{\ifx\next\bgroup \expandafter\fooB\else
\csname foo\the\tmpnum\expandafter\expandafter\expandafter\endcsname\expandafter\fooC\fi}
\def\fooB#1{\addto\fooC{{#1}}\advance\tmpnum by1\futurelet\next\fooA}
\sdef{foo0}{foo without parameters}
\sdef{foo1}#1{foo with one parameter "#1"}
\sdef{foo2}#1#2{foo with two parameters "#1" and "#2"}
\sdef{foo3}#1#2#3{foo with three parameters "#1", "#2" and "#3"}
\sdef{foo4}#1#2#3#4{foo with four parameters "#1", "#2", "#3" and "#4"}
\foo ...
\foo {a} ...
\foo {a}{b} ...
\foo {a}{b}{c} ...
\foo {a}{b}{c}{d} ...
\foo {a}{b}{c}{d}{f} ...
% NormalTeXsyntaxOff
编辑作为示例,上面的代码被打包\multidef
并显示了具有三个具有默认值的参数的宏的用法:
\long\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
\def\ssdef#1{\expandafter\def\csname\string#1\endcsname}
\newcount\tmpnum
\def\multidef#1{%
\def#1{\def\tmpparam{}\tmpnum=0
\expandafter\futurelet\expandafter\next\csname\string#1-A\endcsname}%
\ssdef{#1-A}{\ifx\next\bgroup \csname\string#1-B\expandafter\endcsname\else
\csname \string#1\the\tmpnum\expandafter\expandafter\expandafter\endcsname
\expandafter\tmpparam\fi}%
\ssdef{#1-B}##1{\addto\tmpparam{{##1}}\advance\tmpnum by1
\expandafter\futurelet\expandafter\next\csname\string#1-A\endcsname}%
}
\multidef\foo % the \foo macro with various numbers of parameters is defined here
\ssdef{\foo0}{\fooNormal{defaultA}{defaultB}{defaultC}}
\ssdef{\foo1}#1{\fooNormal{defaultA}{defaultB}{#1}}
\ssdef{\foo2}#1#2{\fooNormal{defaulA}{#1}{#2}}
\ssdef{\foo3}{\fooNormal}
\def\fooNormal#1#2#3{foo invoked: param1=#1, param2=#2, param3=#3}
Test:
\foo ... % does: \fooNormal{defaultA}{defaultB}{defaultC}
\foo {a} ... % does: \fooNormal{defaultA}{defaultB}{a}
\foo {a}{b} ... % does: \fooNormal{defaultA}{a}{b}
\foo {a}{b}{c} ... % does: \fooNormal{a}{b}{c}
这是你想要的嗎?