在命令的定义中出现了 的声明\@dblarg
,如下所示:\def\title{\@dblarg\CJ@title}
。到底\@dblarg
做什么?
答案1
它本质上检查后面的标记是否\CJ@title
存在[
,以便将相同的参数传递给主命令两次,如果[
未找到。该命令\CJ@title
必须定义为
\def\CJ@title[#1]#2{...}
这样,就可以调用如下方法
\title{xyz}
扩张将(连续)
\@dblarg\CJ@title{xyz}
...<some complex action>...
\CJ@title[{xyz}]{xyz}
并调用如下命令
\title[abc]{xyz}
扩张将(连续)
\@dblarg\CJ@title[abc]{xyz}
...<some complex action>...
\CJ@title[abc]{xyz}
我们可以...<some complex action>...
通过查看的定义来理解\@dblarg
:
\long\def\@dblarg#1{\kernel@ifnextchar[{#1}{\@xdblarg{#1}}}
\long\def\@xdblarg#1#2{#1[{#2}]{#2}}
因此,\title{xyz}
有一个(每行一个步骤,我省略了\kernel@ifnextchar
与此无关的扩展)
\@dblarg\CJ@title{xyz}
\kernel@ifnextchar[{\CJ@title}{\@xdblarg{\CJ@title}}{xyz}
\@xdblarg{\CJ@title}{xyz}
\CJ@title[{xyz}]{xyz}
其中\title[abc]{xyz}
一个
\@dblarg\CJ@title{xyz}
\kernel@ifnextchar[{\CJ@title}{\@xdblarg{\CJ@title}}[abc]{xyz}
\CJ@title[abc]{xyz}
第一种情况下有一对多余的括号,但根据 TeX 规则它将被删除;如果标题包含 ,则需要它]
。
如何做同样的事情xparse
通过xparse
包,人们可以获得具有更清晰语法的相同功能(我假设这是在类或包文件中完成的)
\RequirePackage{xparse}
\NewDocumentCommand{\title}{om}{%
\IfNoValueTF{#1}
{\CJ@title{#2}{#2}}
{\CJ@title{#1}{#2}}%
}
\newcommand{\CJ@title}[2]{...}
因此不需要任何限定的参数。
使用最新版本xparse
可以做得更好:
\RequirePackage{xparse}
\NewDocumentCommand{\title}{O{#2}m}{%
\CJ@title{#1}{#2}%
}
\newcommand{\CJ@title}[2]{...}
因为使用此代码,缺少的可选参数提供的值与强制参数相同。
答案2
这是允许其他函数/宏使用可选参数的简单方法。
例如,使用您的案例\def\title{\@dblarg\CJ@title}
,您可以使用
\title{some title}
没有可选参数,或者使用
\title[some optional title]{some title}
和可选参数。这里的“简单”是指,如果你不指定可选组件(如前面的示例),则默认为
\title[some title]{some title}
从而将单参数响应转换为双参数。宏\CJ@title
被适当地定义为管理两个参数,并且可以具有以下形式:
\def\CJ@title[#1]#2{%
%...
}
这通常是具有可选参数的分段命令的情况:\section[<ToC entry>]{<body entry>}
。如果您不指定可选参数,则仍会<body entry>
进入目录。如何?\@dblarg
。
以下是其中包含的正式定义latex.ltx
- 您会在里面找到它的用法\@startsection
,仅作为示例:
\long\def\@dblarg#1{\kernel@ifnextchar[{#1}{\@xdblarg{#1}}}
\long\def\@xdblarg#1#2{#1[{#2}]{#2}}