1.1 Naming functions and variables
我正在阅读有关参数说明符的文档interfaces.pdf
,其中每个参数都由一个字母表示。
我对参数说明符N
和感到困惑n
。文档指出N
和的n
意思是no manipulation of a single token for N
和no manipulation of a set of tokens given in braces for n
。
我需要一些例子,因为我看到很多函数都有N
then n
。这是否意味着该函数接受两个参数?
答案1
用户级命令比 LaTeX 内核中的内部函数少得多。
举个例子,\parbox
它的定义是
\@iparbox \@iiparbox \@iiiparbox \@parboxto
最后一个每次都会被重新定义\parbox
。前三个内部函数的参数文本都不一样,代码读起来比较困难。
也许这个例子具有误导性,但expl3
它的诞生就是为了摆脱这种困难,首先提供一个用于“规范化”参数的层,然后为内部函数提供更清晰的界面。
expl3
我们会以风格
\NewDocumentCommand{\parbox}{O{c}oomm}
{
\innerlevel_parbox:nnnnn {...}
}
将参数传递给具有五个参数的内部函数,如函数签名所明确指定的那样。
签名是冒号后面的内容,应该始终出现在名字里的一个expl3
函数。
例如,\innerlevel_parbox:nnnnn
定义为
\cs_new_protected:Nn \innerlevel_parbox:nnnnn { ... }
其中...
代表使用五个参数的代码。另一种方法是
\cs_new_protected:Npn \outerlevel_parbox:nnnnn #1#2#3#4#5 { ... }
但我发现前一种方法更简单,不需要从函数签名中推断出的代码位。另一方面,后一种版本的效率略高一些。
您会看到\cs_new_protected:Nn
本身已经有一个签名,即Nn
。这告诉程序员它后面应该跟着一个标记(在本例中是控制序列),然后是括号中的参数,这两个参数都不会以任何方式进行操作。
定义之后,程序员知道后面\innerlevel_parbox:nnnnn
应该跟括号中的五个参数。
内核函数的命名准则也有助于记住函数需要哪些参数。例如,
\hbox_set:Nn
期望将 box 变量作为其第一个参数(单个无括号标记),并将一些文本作为第二个参数。一个更复杂的例子是
\int_compare:nNnTF
但是通过一些expl3
编程练习,人们应该能够记住第一个参数应该是“整数表示”,第二个参数应该是<
、=
或>
(单个无括号标记)之间的比较器,第三个表示是另一个“整数表示”,然后是两个分别用于表示测试成功或失败的代码的括号参数。
你提到了“操纵”,这需要一些解释。expl3
是可以定义变体的功能。
我们\cs_new(_protected):Nn
只能定义签名仅由N
或组成的函数n
。但是一旦定义了函数,我们就可以定义其变体。
示例:\hbox_set:Nn
与用户级功能非常相似\sbox
。但假设您想定义一个使用存储在某个宏中的文本的命令,但使用当前的内容,以便提供\sbox
。传统的编程风格需要
\expandafter\sbox\expandafter\mybox\expandafter{\container}
类似物expl3
看起来像
\hbox_set:NV \l_fluffy_my_box \l_fluffy_container_tl
完成后(仅一次,在外层执行此操作)
\cs_generate_variant:Nn \hbox_set:Nn { NV }
因此,签名不仅告诉程序员需要多少个参数:它还允许修改在调用主函数之前函数如何操作参数。
我敢让你写干净地对应于 的代码\innerlevel_parbox:nnnnV
。你不能用一堆\expandafter
' 来做到这一点,但你需要辅助函数进行参数交换,以便将第五个参数放在开头,这样\expandafter
才能有效地使用。相反,expl3
内核已经拥有基础设施来干净地执行任务,而程序员不需要知道魔法是如何发生的。