有时我会定义模型命令(\foo
如下例所示),然后根据该模型定义特定命令(\fool
如下例所示)。但是,我并不完全确定我使用的语法是否正确。
\documentclass{minimal}
\usepackage{xparse}
\NewDocumentCommand\foo{mm}{#2#1}
\NewDocumentCommand\fool{}{\foo!}
\NewDocumentCommand\foot{m}{\foo!{#1}}
\begin{document}
\fool{⟨sth⟩}, \foot{⟨sth⟩}
\end{document}
\fool
和 的行为不同吗\foot
?一个比另一个好吗?据我了解,和都\fool{⟨sth⟩}
扩展\foot{⟨sth⟩}
到,\foo!{⟨sth⟩}
然后扩展到⟨sth⟩!
,这是预期的结果。这样对吗?
答案1
TeX 是一种宏扩展语言。如果我们查看 中的一些随机定义plain.tex
,我们会发现一些仅出现发生争论。例如
\def\line{\hbox to\hsize}
应该称为\line{text}
。因此,看似 的参数\line
实际上是 的参数\hbox to\hsize
。
\makebox
LaTeX 模型更加复杂。例如,
\DeclareRobustCommand\makebox{%
\leavevmode
\@ifnextchar(%)
\@makepicbox
{\@ifnextchar[\@makebox\mbox}}%
其中有不参数。获取参数将延迟到\@makepicbox
、\@makebox
或\mbox
,具体取决于后面的标记。
也采用了同样的方法。如果你在定义之后xparse
再看一下 的定义,你会看到\foo
> \foo=\protected macro:
->\__xparse_start_expandable:nNNNNn {mm}\foo \foo \foo code ?{\__xparse_expandable_grab_m:w \__xparse_expandable_grab_m:w }.
so\foo
没有参数(像\makebox
)。参数实际上是通过\foo•code
(项目符号表示名称中的空格)以相当复杂的方式获取的,因为目的是能够指定强制或可选参数的复杂序列。以下是它的定义:
> \foo code=\protected\long macro:
#1#2->#2#1.
另一方面,如果你这样做
\NewDocumentCommand{\foo}{O{x}m}
那么的定义\foo
就是
> \foo=\protected macro:
->\__xparse_start:nNNnnn {O{x}m}\foo \foo code {\__xparse_grab_D:w []\__xparse_grab_m_1:w }{{\prg_do_nothing: x}\c__xparse_no_value_tl }{}.
但\foo•code
会和以前一样。
对于\fool
和 也类似\foot
。两个版本最终都会以相同的方式工作,因为两者都会以
\foo•code ! {(sth)}
在主输入流中。
唯一的区别是第二个参数用 读取两次,\foot
用 只读取一次\fool
。总的来说,节省的时间并不值得。
使用和朋友时,建议\NewDocumentCommand
始终指定完整的参数集。然而,有些情况下使用“简化”版本更简单,但应将其保持在最低限度,以最大限度地提高代码的可读性。