你使用 \tableofcontents
然后查看 .toc 文件就能看到区别。可以再定义一个 expandable document cmd,放在 \section
里,再看看目录文件。
“展开”与上下文有关,需要区分“展开”和“执行”。“展开”是宏替换,把宏替换为其它东西。
在正常的上下文中,读入、展开、执行、输出这四个依次交替执行,这是一般情形。在所谓的“完全展开”的上下文中,比如 \expanded
的“参数”(也就是 latex3的 e 型展开),还有用 \write
把“参数”写入文件等等,这些参数都会被“展开”,但不会“执行”,“赋值”操作不会生效的。还有 f 型的展开,和 \csname
\endcsname
之间的内容的展开。
与之相关的还有 protected 宏、robust 宏。前者不会在 e 型展开中被展开(但在正常的上下文中仍然会被展开)。后者是没有 protected 宏的时代为了阻止宏被展开的一个 trick。
interface3.pdf 中命令标有实心星号的可以在 e 型和 f 型中安全的展开,空心星号的可以在 e 型但不能在 f 型中安全的展开。
这些是下面要讲的内容的基础。
\NewDocumentCommand
定义的命令是 protected 宏,e 型展开不会展开它,所以写入文件时、做为 \expanded
的参数等情形,它都保持不变;而不是 protected 宏,比如 expandable document cmd,则会被替换为它的“替换文本”,这个替换是完全替换,也就是在此上下文中所有能被替换的都会替换,这种替换也就是“完全展开”。
要构造非得用 expandable document cmd 的情形,就比如在会展开而不会执行的上下文中,比如 \tl_set:Ne
,\str_set:Ne
,然后用 \tl_show:N
查看它的值。你的例子只要把 \section
替换为 \tl_set:Ne
就好了。
另外,我们知道,latex3 除了有 int 类型,还有一种特殊的类型:flag,可以自己试试在 e 型展开中 \int_incr:N
和 \flag_raise:N
有何区别。
问 何时需要使用NewExpandableCommand?能否给一个最简单例子说明何为完全展开