我在写一个宏命令 \MyCMD
,它有一个参数。
但这个参数本身包含不确定个数的tokens。
比如:\MyCMD{{par 1}{par 2}{par 3}}
在原始版本中每一个参数都传递给另一个命令 \__MyCMD_deal:n
进行外理。
现在我需要将 \__MyCMD_deal:n
升级为 \__MyCMD_deal_newversion:nn
,它多吸收一个可选参数。
此时 \MyCMD
命令依然只有一个参数,它的用法类似: \MyCMD{{par 1}[opt 1]{par 2}{par 3}[opt 3]}
。
显然在 \MyCMD
中无法再用 \tl_map_inline:nn
来分割参数。
现在这个 \MyCMD
怎么写呢?
代码逻辑如下:
\documentclass{article}
\ExplSyntaxOn
\cs_new:Npn \__MyCMD_deal:n #1
{
output: #1 \par %伪应用
}
\NewDocumentCommand{\__MyCMD_deal_newversion:nn}{+m+O{}}
{
output: #1 ~ option: #2 \par %伪应用
}
\NewDocumentCommand{\MyCMD}{+m}
{
\tl_map_inline:nn {#1}
{
\__MyCMD_deal:n {##1}
}
}
\ExplSyntaxOff
\begin{document}
\MyCMD{{par 1}{par 2}{par 3}}
\MyCMD{{par 1}{par 2}}
%\MyCMD{{par 1}[opt 1]{par 2}[opt 2]{par 3}[opt 3]}
%\MyCMD{{par 1}[opt 1]{par 2}[opt 2]}
%\MyCMD{{par 1}{par 2}[opt 2]{par 3}}
\end{document}
使用尾递归即可,这是比较常见的处理方式,\tl_map_..
也是用尾递归实现的。
\documentclass{article}
\ExplSyntaxOn
\cs_new:Npn \__MyCMD_deal:n #1
{
output: #1 \par %伪应用
}
\quark_new:N \q__MyCMD_stop
\NewDocumentCommand{\__MyCMD_deal_newversion:nw}{+m+O{}}
{
\tl_if_eq:nnF {#1} { \q__MyCMD_stop }
{
output: #1 ~ option: #2 \par %伪应用
\__MyCMD_deal_newversion:nw
}
}
\NewDocumentCommand{\MyCMD}{+m}
{
\__MyCMD_deal_newversion:nw #1 \q__MyCMD_stop []
}
\ExplSyntaxOff
\begin{document}
\MyCMD{{par 1}{par 2}{par 3}}
\MyCMD{{par 1}{par 2}}
\MyCMD{{par 1}[opt 1]{par 2}[opt 2]{par 3}[opt 3]}
\MyCMD{{par 1}[opt 1]{par 2}{par 3}[opt 3]}
\MyCMD{{par 1}[opt 1]{par 2}[opt 2]}
\MyCMD{{par 1}{par 2}[opt 2]{par 3}}
\end{document}
由于不需要可展的实现,可以用 \tl_if_eq:nn
比较,无需可展的 \quark_if_..
,这样更快。