答案1
你指的是
\cs_new_protected:Npn \malmedal_output_direct:
{
\int_zero:N \l_malmedal_count_int
\seq_map_inline:Nn \g_malmedal_input_seq
{
\int_incr:N \l_malmedal_count_int
\malmedal_print:n { ##1 }
}
}
让我们看看它是如何\seq_map_inline:Nn
工作的。根据惯例,第一个参数应该是单个标记,在本例中是序列的名称;第二个参数必须是标记的括号列表。这个(以及大多数其他映射函数)的工作方式是将代码呈现在第二个参数中,序列的每个元素一个接一个。这条信息由#1
(因为开发人员选择了它,而且它是非常方便):因此“裸”调用\seq_map_inline:Nn
通常采用以下形式
\seq_map_inline:Nn \l_some_seq { \some_cs:n { #1 } }
(但第二个参数中可以使用任何其他代码)。但是,在上面的代码中,函数出现在定义的替换文本中,因此适用旧的 TeX 规则,其中
\def\x#1{\def#1##1{--##1--}}
是一个典型的例子:调用\x{\y}
将被替换为
\def\y#1{--#1--}
这就是 Knuth 如何允许将带有参数的宏定义放在其他定义中;规则是,当扫描替换文本时,单数后面#
必须跟着一个数字1
,从而9
表示一个参数;但是当在宏扩展期间使用替换文本时,单数##
将简化为单数。#
换句话说,当\malmedal_output_direct:
扩展时,##1
将会变成#1
并且让 TeX 保持满意,因为代码将如预期的那样(如上面的典型示例所示)。