假设你有一个对三个 token 进行操作的函数,
\cs_new:Nn \@@_on_three:NNN { #1, #2, #3 }
并且您有一个变量,其值是三个标记:
\tl_set:Nn \l@@_three_tl { foo }
你想有一个变体
\@@_on_three:V
所以你可以说
\@@_on_three:V \l@@_three_tl
但是,如果我没有记错的话,直接\cs_generate_variant
会被不同数量的参数(NNN
vs.V
或x
)所混淆,并且在任何情况下它都会传递扩展的参数在括号内, 正确的?
因此,您需要一种“假”变体,定义为:
\cs_new:Nn \@@_on_three:V
{ \exp_last_unbraced:Nx \@@_on_three:NNN #1 }
要明确的是:这有效。我的问题在于,是否有其他不那么“淘气”的方法可以做到这一点——更少的中级欺骗expl3
。
答案1
定义
\cs_new:Nn \@@_on_three:V
{ \exp_last_unbraced:Nx \@@_on_three:NNN #1 }
expl3
是编程“错误”的指导方针。 V
-type 变量应该与 -type 底层函数相关n
,并且不应该对正在处理的变量的内容做出假设。例如,
\tl_set:Nn \l_@@_three_tl { A }
给定的定义\@@_on_three:V
?另外,您使用的是x
-type 扩展而不是V
-type 扩展,如果传递的变量是 TeX 寄存器,或者它包含类似 LaTeX2e 'protected' 代码的内容,则这将失败。
要明确的是:创建变体时不需要使用\cs_generate_variant:Nn
,但“要求”它们的行为与使用时相同。例如,有各种手动调整的变体l3tl
,但这只是为了提高性能,而不会改变行为。另请参见我们最近收紧了许多x
-type 变体的事实,因为它们在这方面没有显示正确的结果。
问题没有说明,但读起来好像tl
这里用来存储一些结构化数据,这些数据总是由三个标记组成。因此,似乎想要的是
\cs_new:Nn \@@_on_three:N
{ \exp_last_unbraced:No \@@_on_three:NNN #1 }
其中的语义是\@@_on_three:N
应该与包含三个标记的一起使用tl
。这在低级工作中很常见,并且类似的代码例如在实验输出例程(xor
)的部分中使用(我应该对其进行修订)。