expl3
在将参数传递给基函数之前,分别包括用于单级扩展和两种完全扩展的、和参数说明符。扩展参数的首选方法o
是f
什么x
两次在将其传递给基本函数之前?
举个例子,我正在尝试为从包中l3keys
创建的宏编写一个键值接口。\DeclarePairedDelimiter
mathtools
\tl_new:N \l__mymodule_size_tl
\keys_define:nn { mymodule }
{
size .choices:nn =
{ big , Big , bigg , Bigg }
{
\tl_set:Nn \l__mymodule_size_tl
{ [ \use:c { \tl_use:N \l_keys_choice_tl } ] }
} ,
size / auto .code:n =
\tl_set:Nn \l__mymodule_size_tl {*} ,
size / none .code:n =
\tl_clear:N \l__mymodule_size_tl
}
\big
通常,分隔符的大小作为etc. 或的可选参数传递给宏,*
例如\abs[\big]{x}
where \DeclarePairedDelimiter\abs{\lvert}{\rvert}
。我更喜欢将size = big
etc. 或size = auto
作为键值接口,例如\myabs[size=big]{x}
。
上述代码的问题在于正确设置等\l__mymodule_size_tl
选项big
:我需要扩展[ \use:c { \tl_use:N \l_keys_choice_tl } ]
两次在将这些标记分配给之前\l__mymodule_size_tl
。
- 如果我不使用扩展(即
\tl_set:Nn
),则对的调用\abs
将以错误的形式获取其参数——\l__mymodule_size_tl
将保留[ \use:c { \tl_use:N \l_keys_choice_tl } ]
,而不是[\big]
。 - 如果我使用一级扩展(即),并在扩展完成后
\tl_set:No
添加,将保持,而不是。[
\l__mymodule_size_tl
[ \cs:w \tl_use:N \l_keys_choice_tl \cs_end: ]
[\big]
- 如果我使用
f
或x
扩展,\l__mymodule_size_tl
将会保存一堆“垃圾”,而不是[\big]
。
我能做什么?这里有一个想法:使用两个o
扩展,中间进行一些杂技。
\tl_set:No \l__mymodule_size_tl
{ \use:c { \tl_use:N \l_keys_choice_tl } ] }
\exp_args:NNV \tl_set:No \l__mymodule_size_tl
\l__mymodule_size_tl
\tl_put_left:Nn \l__mymodule_size_tl { [ }
在我看来,这太丑了。我还能做些什么更好的事情吗?
答案1
在过去,有一个d
用于双扩展的 -type 参数。然而,几年前它被放弃了,因为很少有地方需要它,特别是当团队决定不再使用toks
寄存器时。从记忆中,expl3
有两个地方我们必须使用或类似形式的构造\exp_args:NNo \exp_args:No
。
我们没有保留 -type 参数的原因d
有两个。首先,我们希望尽可能避免依赖于了解函数的扩展细节:这对于低级工作是必需的,但理想情况下应该相对有限。另一个原因是,由于我们有 e-TeX,所以很少需要它。要记住的关键是,这使我们能够控制x
-type 上下文中的扩展
\tl_set:Nx \l__mymodule_size_tl
{ [ \exp_not:c { \tl_use:N \l_keys_choice_tl } ] }
虽然这里不需要,但我们确实记录了\cs:w
需要\cs_end:
一次扩展的情况,因此您可以
\tl_set:No \l__mymodule_size_tl
{ \exp_after:wN [ \cs:w \tl_use:N \l_keys_choice_tl \cs_end: ] }
尽管我自己不会在这里使用它。
答案2
我的印象是你想做
\tl_set:Nx \l__mymodule_size_tl
{
[ \exp_not:c { \tl_use:N \l_keys_choice_tl } ]
}
触发x
扩展,因此当涉及到时(它是) \exp_not:c
,参数会像往常一样完全扩展;然后生成的标记将变得不可扩展,所以如果你有c
\csname...\endcsname
size=big
您将进入[\big]
您的令牌列表。