在 LaTeX3 中向映射函数传递更多参数

在 LaTeX3 中向映射函数传递更多参数

在 LaTeX3 中,我们可以写下这些行:

\cs_new_nopar:Nn \module_main:nn #1#2
  {
    \clist_map_function:NN \g_module_some_clist \module_mapping:n
  }  
\cs_new_nopar:Nn \module_mapping:n #1
  {
    % #1 is the clist item
  }

现在我还想将 的两个参数传递\module_main:nn\module_mapping。除了定义两个类似于\clist_map_function:NN和 的新函数外,还有什么简单的方法可以做到这一点\__clist_map_function:Nw

为了获得全面扩展,我无法使用\clist_map_inline

答案1

标准映射函数适用于简单的情况,即您想要将映射的标记传递给某些预定义的辅助函数。在非扩展上下文中,您可以动态定义辅助函数以包含其他数据

\cs_new_protected:Npn \module_main:N #1
  {
    \cs_set_protected:Npn \__module_aux:n ##1
      {
        % Code using #1
      }
    \clist_map_function:NN \l__module_clist \__module_aux:n
  }

或者如您所注,使用\clist_map_inline:Nn。第一种方法可用于包装器不需要扩展但映射需要扩展的情况,而第二种方法则不能。

对于完全可扩展映射,预期是人们将使用通用工具来定义递归:不可能预测每个用例。例如,我们可能有

\cs_new:Npn \module_main:N #1
  {
    \exp_after:wN \__module_loop:Nw \exp_after:wN #1
      \l__module_clist , \q_recursion_tail , \q_recursion_stop
  }
\cs_new:Npn \__module_loop:Nw #1#2 ,
  {
    \quark_if_recursion_tail_stop:n {#2}
    % Code using #1 and #2
    \__module_loop:Nw #1 % Loop passing #1 from \module_main:N 
  }

传递大量的像这样的参数可能会很棘手,可能需要辅助函数对参数进行“改组”,例如

\cs_new_nopar:Npn \module_main:Nnn 
  {
    \__module_aux:VNnn \l__module_clist
  }
\cs_new:Npn \__module_aux:nNnn #1#2#3#4
  {
      \__module_loop:Nnnw #2 {#3} {#4}
        #1 , \q_recursion_tail , \q_recursion_stop
  }
\cs_generate_variant:Nn \__module_aux:nNnn { V }
\cs_new:Npn \__module_loop:Nnnw #1#2#3#4 ,
  {
    \quark_if_recursion_tail_stop:n {#4}
    % Code using #1 to #4
    \__module_loop:Nnnw #1#2#3 % Loop passing args from \module_main:Nnn
  }

对于您想要对输入进行测试并且仅在一种情况下使用其他参数的情况,您可以将后者留在输入流中并执行类似操作

\cs_new_nopar:Npn \module_main:Nnn 
  {
    \exp_after:wN \__module_loop:wNnn
        \l__module_clist , \q_recursion_tail , \q_recursion_stop
  }
\cs_new:Npn \__module_loop:wNnn #1 ,
  {
    \quark_if_recursion_tail_stop_do:nn {#1} ( \use_none:nnn }
    \str_if_eq:nnT {#1} { fixed-string }
      {
        \use_i_delimit_by_q_recursion_stop:nw { \__module_aux:nNnn {#1} }
      }
    \__module_loop:wNnn
  }
\cs_new:Npn \__module_aux:nNnn #1#2#3#4
  {
    % Do stuff
  }

where\use_i_delimit_by_q_recursion_stop:nw让我们跳出循环并插入辅助和命中,\use_none:nnn如果没有命中则进行清理。

更一般地,\use_none_delimit_by_q_recursion_stop:w/\use_i_delimit_by_q_recursion_stop:nw可用于提前终止通用递归,而不管传递了多少个参数,因此我们可以将上述方法之一修改为

\cs_new_nopar:Npn \module_main:Nnn 
  {
    \__module_aux:VNnn \l__module_clist
  }
\cs_new:Npn \__module_aux:nNnn #1#2#3#4
  {
      \__module_loop:Nnnw #2 {#3} {#4}
        #1 , \q_recursion_tail , \q_recursion_stop
  }
\cs_generate_variant:Nn \__module_aux:nNnn { V }
\cs_new:Npn \__module_loop:Nnnw #1#2#3#4 ,
  {
    \quark_if_recursion_tail_stop:n {#4}
    \test:T % Terminate the loop early
      {
        \use_none_delimit_by_q_recursion_stop:w
      }
    \__module_loop:Nnnw #1#2#3 % Loop passing args from \module_main:Nnn
  }

相关内容