expl3 中的“假”变体

expl3 中的“假”变体

假设你有一个对三个 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会被不同数量的参数(NNNvs.Vx)所混淆,并且在任何情况下它都会传递扩展的参数在括号内, 正确的?

因此,您需要一种“假”变体,定义为:

\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)的部分中使用(我应该对其进行修订)。

相关内容