LaTeX3 中的 \use_none_delimit_by_q_nil:w 及其朋友的用途是什么?

LaTeX3 中的 \use_none_delimit_by_q_nil:w 及其朋友的用途是什么?

该包的 LaTeX3 文档l3basics列出了三个函数

\use_none_delimit_by_q_nil:w            ... \q_nil
\use_none_delimit_by_q_stop:w           ... \q_stop
\use_none_delimit_by_q_recursion_stop:w ... \q_recursion_stop

带有分隔参数,它们都...从输入流中删除该部分。另外:nw定义了三个变体,它们删除该...部分但将其第一个参数放回到输入流中。

我想知道这些函数应该用来做什么。当起始命令和终止标记必须分布在代码中的两个不同位置时,读取由终止标记分隔的参数有时非常有用。

但是,这里有三个这样的函数,其名称表明这些函数应该在特殊情况下使用。它们还会从输入中删除它们收集的标记,这对于递归函数来说似乎很奇怪;收集标记并将其作为最终结果返回对我来说似乎更有用。

那么这些功能的预期用途是什么?

答案1

它们的目的正是您所期望的:删除最多一个给定的标记。但是,由于标记必须匹配确切地用例的结束。我们需要多个唯一的标记,特别是对于可扩展循环(使用\q_recursion_stop)。根据确切的设置,可能会有嵌套标记,或者可能出于其他原因,其中一个或另一个是可取的。因此,我们有一个小集合,基于“通用”结束标记。

虽然我们(团队)有一些更复杂的核心循环结构,但“通用循环”代码很好地说明了分隔结尾的使用。例如,假设我们想要以三个标记为一组循环遍历某个输入数据结构。我们可以将其设置为

\input expl3-generic %
\ExplSyntaxOn

\cs_new:Npn \siracusa_loop:n #1
  {
    \__siracusa_loop:NNN
      #1
      \q_recursion_tail \q_recursion_tail \q_recursion_tail
      \q_recursion_stop
  }
\cs_new:Npn \__siracusa_loop:NNN  #1#2#3
  {
    \quark_if_recursion_tail_stop:n {#3}
    \quark_if_recursion_tail_stop:n {#2}
    \quark_if_recursion_tail_stop:n {#1}
    \tl_show:n { First ~"#1";~Second:~"#2";~Third~"#3" }
    \__siracusa_loop:NNN
  }
\siracusa_loop:n { ABC }

\siracusa_loop:n { ABC 123 }

\siracusa_loop:n { ABC D }
\siracusa_loop:n { ABC DE }

\tex_end:D

此处,“清理”隐藏在 内\quark_if_recursion_tail_stop:n,需要\use_none_delimit_by_q_recursion_stop:w。极少数情况下,可能需要手动执行此操作:通常在需要进行复杂改组的情况下。

答案2

根据 Joseph Wright 非常有用的回答,我认为我现在理解了这种函数背后的想法。我玩了一下,想出了一个\use_i_delimit_by_*可以使用类似函数集的示例:

\input expl3-generic %
\ExplSyntaxOn

\cs_new:Npn \siracusa_loop:n #1
  {
    \__siracusa_loop:NNN
      #1
      \q_recursion_tail \q_recursion_tail \q_recursion_tail
      \q_recursion_stop
  }

\cs_new:Npn \__siracusa_loop:NNN  #1#2#3
  {
    \siracusa_check_for_rest:Nn {#1} { }
    \siracusa_check_for_rest:Nn {#2} { \tl_show:n { Rest ~"#1" } }
    \siracusa_check_for_rest:Nn {#3} { \tl_show:n { Rest ~"#1#2" } }
    \tl_show:n { First ~"#1";~Second:~"#2";~Third~"#3" }
    \__siracusa_loop:NNN
  }

\cs_new:Npn \siracusa_check_for_rest:Nn #1#2
  {
    \tl_if_empty:oT { \__quark_if_recursion_tail:w {} #1 {} ?! \q_recursion_tail ??! }
        {\use_i_delimit_by_q_recursion_stop:nw { #2 } }
  }

\siracusa_loop:n { ABC }

\siracusa_loop:n { ABC 123 }

\siracusa_loop:n { ABC D }
\siracusa_loop:n { ABC DE }

\tex_end:D

的定义\siracusa_check_for_rest:Nn基于 的\quark_if_recursion_tail_stop:n定义,只是用\use_i_delimit_by_q_recursion_stop:nw代替\use_none_delimit_by_q_recursion_stop:w。(这些名字到底是谁想出来的?;))

我们现在还可以在输出中获得剩余的输入标记:

第一个“A”;第二个:“B”;第三个“C”

第一个“A”;第二个:“B”;第三个“C”
第一个“1”;第二个:“2”;第三个“3”

第一页“A”;第二页:“B”;第三页“C”
其余部分“D”

第一个“A”;第二个:“B”;第三个“C”
其余“DE”

相关内容