![expl3 宏可扩展地迭代列表并对每个项目应用宏](https://linux22.com/image/418803/expl3%20%E5%AE%8F%E5%8F%AF%E6%89%A9%E5%B1%95%E5%9C%B0%E8%BF%AD%E4%BB%A3%E5%88%97%E8%A1%A8%E5%B9%B6%E5%AF%B9%E6%AF%8F%E4%B8%AA%E9%A1%B9%E7%9B%AE%E5%BA%94%E7%94%A8%E5%AE%8F.png)
如果可能的话,有人能告诉我如何\applyeach
使用来扩展以下宏()吗?expl3
\documentclass{article}
\newcounter{applyeachposition}
\newcommand\applyeachmacro{}
% #1 : macro to apply
% #2 : multi-args
\newcommand\applyeach[2]{
\setcounter{applyeachposition}{0}
\renewcommand\applyeachmacro{#1}
\applyeachrecu#2|\nil
\renewcommand\applyeachmacro{}
}
\def\applyeachrecu#1|#2\nil{
\stepcounter{applyeachposition}
\applyeachmacro{#1}
\if\relax\detokenize{#2}\relax\else
\applyeachrecu#2\nil
\fi
}
\newcommand\decoone[1]{%
[(\textbf{#1})] \quad%
}
\newcommand\multiapply[1]{%
\applyeach{\decoone}{#1}
}
\begin{document}
\multiapply{1|12|123|1234}
\end{document}
答案1
由于无法更改分隔符,因此定义非常简单。不过请注意,正如 egreg 所说,设置计数器是一种赋值,而赋值是不是可扩展,所以您不能使用它们。您必须“动态”增加一个数字并将其传递给宏,但不能将其作为计数器。
宏本身在 a 处拆分参数,|
并对其应用给定函数,直到循环结束。添加 a \prg_do_nothing:
(稍后再删除)会处理参数周围的括号项和空格。如果您需要更改分隔符,那么代码将变得更加复杂。
我这样定义\multiapply<cmd>{<list>}
它,使其在|
-separated上迭代<list>
并应用于<cmd>
每个项目。需要<cmd>
采用两个参数:#1
是列表中项目的编号,#2
是项目本身。
\documentclass{article}
\ExplSyntaxOn
\NewExpandableDocumentCommand \multiapply { m +m }
{ \mbc_multiapply:Nn #1 {#2} }
\cs_new:Npn \mbc_multiapply:Nn #1 #2
{
\__mbc_multiapply:nNw { 0 } #1
| \prg_do_nothing: #2 | \q_recursion_tail | \q_recursion_stop
}
\cs_new:Npn \__mbc_multiapply:nNw #1 #2 | #3 |
{ \exp_args:Nof \__mbc_multiapply:nnN {#3} { \int_eval:n {#1+1} } #2 }
\cs_new:Npn \__mbc_multiapply:nnN #1 #2 #3
{
\quark_if_recursion_tail_stop:n {#1}
\exp_not:e { \exp_not:N #3 {#2} { \tl_trim_spaces:n {#1} } }
\__mbc_multiapply:nNw {#2} #3 | \prg_do_nothing:
}
\ExplSyntaxOff
\newcommand\decoone[2]{%
Item #1: [(\textbf{#2})]\quad}
\begin{document}
\multiapply\decoone{ 1 | 12 | 123 | 1234 }
\end{document}