在 LaTeX3 中,我应该使用标记列表还是(无参数)控制序列?
例如,我需要使用某些格式的宏\itshape
,那么哪一个更好?
\tl_new:N \l__mydoc_format_tl
\tl_set:Nn \l__mydoc_format_tl { \itshape }
或者
\cs_new:Nn \__mydoc_format: { \itshape }
答案1
从这两个例子中你得到的结果没有太大的区别:和都\l__mydoc_format_tl
变成\__mydoc_format:
了扩展为的 TeX 宏\itshape
。从
\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\tl_new:N \l__mydoc_format_tl
\tl_set:Nn \l__mydoc_format_tl { \itshape }
\cs_new:Nn \__mydoc_format: { \itshape }
\show\l__mydoc_format_tl
\show\__mydoc_format:
\show
为了不增加任何可能的怀疑,我故意使用
> \l__mydoc_format_tl=macro:
->\itshape .
l.10 \show\l__mydoc_format_tl
?
> \__mydoc_format:=\long macro:
->\itshape .
l.11 \show\__mydoc_format:
如果我们使用\cs_new_nopar:Nn
,这两个宏将是\ifx
等效的。
这种区别更多的是概念上的,而不是技术上的。 标记列表变量(例如)\l__mydoc_format_tl
是容器,而函数(例如)则\__mydoc_format:
用于“执行某项操作”。 几乎所有编程语言中都存在类似的区别,但在经典 (La)TeX 编程中却很模糊,因为除了寄存器之外,TeX 只有宏。
自项目开始以来,LaTeX3 团队就认为应该做出区分,以使程序更具可读性。
你如何在这两种类型之间做出选择?这取决于使用新对象。
令牌列表变量是作为我们计划在某个时间点交付的令牌的容器,或者我们需要与其他令牌列表进行比较。您可以地图通过一个 token 列表,这对于函数来说(概念上)毫无意义。函数做变量是用过的按功能。
然而,是两者之间存在技术差异。如果你将上面的分配更改为
\tl_set:Nn \l__mydoc_format_tl { ## }
\cs_new:Nn \__mydoc_format: { ## }
你会看到的
> \l__mydoc_format_tl=macro:
->####.
l.10 \show\l__mydoc_format_tl
?
> \__mydoc_format:=\long macro:
->##.
l.11 \show\__mydoc_format:
因此标记列表变量包含二 #
标记(\show
打印两份),而函数扩展为单个#
标记。
顺便说一句,如果您打算使用一个执行特定字体选择的功能,它应该受到“保护”:
\cs_new_protected:Nn \__mydoc_format: { \itshape }
因为这个函数所做的事情并不是“可扩展的”,所以我们不会冒着该函数在某些情况下(比如写操作)不合时宜地扩展的风险。