20 LaTeX3中控制宏展开的参数说明符x和e有啥区别?

发布于 2023-05-18 20:01:44

LaTeX3中控制宏展开的参数说明符中有x型和e型,都表示完全展开,请问两者具体的区别是啥?比如下面这两个函数:

\use:x{<可展开的记号>}
\use:n{<可展开的记号>}

二者的区别在何处?

查看更多

关注者
0
被浏览
1k
雾月
雾月 2023-05-18
这家伙很懒,什么也没写!

这两个宏都需要吃掉一个参数,并且完全展开这个参数。

第一个区别是,\use:e(在要被完全展开的上下文中)可以被完全展开(expands all tokens fully),\use:x 不能被完全展开。
比如 \use:e { <tl> }<tl> 就是“要被完全展开的上下文”,如果这里面有 \use:e,它也会被完全展开,\use:x 则不会被展开。
例如,

% protected 宏 \__my_unexp: 在要被完全展开的上下文中不会被展开,保持原样
\cs_set_protected:Npn \__my_unexp: { do~something }
\tl_set:Nn \l__my_tl { do~other }

\use:e { \__my_unexp: \use:x { \l__my_tl } }

其结果是 \__my_unexp: \use:x { do~other }\__my_unexp:\use:x 不会被展开,括号也不会被展开,但是 \l__my_tl 会被展开,这个展开是由 \use:e 引起的,而不是 \use:x

\use:e { \__my_unexp: \use:e { \l__my_tl } }

的结果是 \__my_unexp: do~other\__my_unexp: 不会被展开,但是里面的 \use:e 会被展开,它需要一个参数,即 \l__my_tl,然后这个里面的 \use:e 展开它的参数 \l__my_tl
有没有办法阻止记号在要被完全展开的上下文中被展开呢?有。就是 \exp_not:N\exp_not:n(及其变体)。

\use:e { \__my_unexp: \exp_not:N \use:e { \l__my_tl } }

这样,里面的那个 \use:e 就不会被展开,但 \l__my_tl 会被外面那个 \use:e 展开,结果是 \__my_unexp: \use:e { no~other }

\use:e { \__my_unexp: \exp_not:n { \use:e { \l__my_tl } } }

结果是 \__my_unexp: \use:e { \l__my_tl },因为 \exp_not:n 的作用是让它的参数不被展开。
以上代码把外面的那个 \use:e 换成 \use:x,结果完全相同。

另一个区别是,\use:x 的参数中,parameter(catcode=6),比如 #,需要双写,但 \use:e 不需要,如:

\use:x { \cs_set:Npn \exp_not:N \__foo_do:n #1 { } }
\use:e { \cs_set:Npn \exp_not:N \__foo_do:n #1 { } }

第一行会报错。需要写成 ##1

除此之外,它们的作用完全相同。

l3kernel 昨天(2023-05-17,版本为 Released 2023-05-15)的更新中,要求引擎必须有 \expanded primitive 了(从 TeXLive 2019 开始 pdfTeX、XeTeX、LuaTeX 都已经有这个 primitive 了),\use:e 也是使用 \expanded 实现的。
目前,有 e 变体的应当用这个变体,使用 \cs_generate_variant:Nn 时,也应生成 e 变体。
某些宏和 primitive,比如 \tl_set:Nx\cs_set_nopar:Npx,它们内部使用的 primitive 已经完成了完全展开这个操作,所以不再需要使用 e 变体来展开。(当然不全是如此)

TeX(和 LaTeX)里关于“展开”的内容可以写一篇10页以上的文章了。

1 个回答

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览