尝试理解 l3prop 的代码片段

尝试理解 l3prop 的代码片段

查看 l3prop 的实现代码,我对以下部分(在 \prop_remove:Nn 的定义中)感到困惑:

\cs_new_protected:Npn \__prop_split:NnTF #1#2
  { \exp_args:NNo \__prop_split_aux:NnTF #1 { \tl_to_str:n {#2} } }


\cs_new_protected:Npn \__prop_split_aux:NnTF #1#2#3#4
  {
    \cs_set:Npn \__prop_split_aux:w ##1
      \__prop_pair:wn #2 \s__prop ##2 ##3 \s__prop_mark ##4 ##5 \s__prop_stop
      { ##4 {#3} {#4} }
    \exp_after:wN \__prop_split_aux:w #1 \s__prop_mark \use_i:nn
      \__prop_pair:wn #2 \s__prop { } \s__prop_mark \use_ii:nn \s__prop_stop
  }


\cs_new:Npn \__prop_split_aux:w { }


\cs_new_protected:Npn \prop_remove:Nn #1#2
  {
    \__prop_split:NnTF #1 {#2}
      { \tl_set:Nn #1 { ##1 ##3 } }
      { }
  }

我对 \__prop_split:NnTF 的定义感到困惑......更确切地说,我的解释(从代码,而不是函数签名)它是一个只有两个参数 #1 #2 的宏(尽管签名建议有 4 个参数(TF 部分))。

更重要的是使用/定义 \__prop_split_aux:NnTF,它被定义为一个具有 4 个参数的宏,但是使用时(在 \__prop_split:NnTF 中)只给出两个参数......

这是怎么回事?(或者我遗漏了哪些定义?)

谢谢你的帮助。

编辑:不要忘记 \__prop_split_aux:w 的奇怪(对我来说)定义,我的意思是,从 \cs_set:Npn 的签名来看,我期望一个 csname (\__prop_split_aux:w) 一个参数“列表”(##1),然后是“代码”本身(平衡),但我看到的却(?!)只是一个标记(\__prop_pair:wn)

答案1

每次 TeX 解析参数时,它都需要一点时间,如果它不必要地拾取参数,它就会需要一点不必要的额外时间。因此,时间紧迫的应用程序会避免这种情况(如果不需要的话)(这是一种常用技术,并不特定于 L3 编程层)。

\__prop_split:NnTF直接选取 2 个参数并处理它们。作为其最终操作,它调用为其提供 2 个参数。由于该命令需要 4 个参数,因此它从输入流中获取缺少的 2 个 (TF)。这与选取 4 个参数并像这样结束的\__prop_split_aux:NnTF情况相同:\__prop_split:NnTF

\cs_new_protected:Npn \__prop_split:NnTF #1#2#3#4
  { \exp_args:NNo \__prop_split_aux:NnTF #1 { \tl_to_str:n {#2} } {#3} {#4} }

速度较慢的原因在于,一个命令可能很长#3#4现在需要读取两次并传递。对于在文档中调用数千次的命令,即使在快速机器上,随着时间的推移,这些命令也会累积起来。

我同意下面@egreg的评论!以上是对您所展示的代码中发生的事情的解释,而不是建议您在自己的代码中使用它。进行这些优化意味着为了获得最小的速度改进而降低代码的可读性。这只在少数地方是合理的(内核的部分符合条件,但软件包或用户代码很少符合条件)。这是内核代码不一定是学习如何在高级代码中使用 L3 程序层的最佳场所的原因之一。

相关内容