如何在“expl3”[而不是“xparse”]的上下文中拆分参数?

如何在“expl3”[而不是“xparse”]的上下文中拆分参数?

SplitArgument{<sep>}我正在尝试在 内做类似的事情expl3。现在我修复了<sep>=;。但我没有取得很大进展:

\documentclass{report}
\usepackage{xparse}

\ExplSyntaxOn

\cs_new:Nn \__erw_inner:nnn{(#1)(#2)(#3)}

\cs_new:Nn \__erw_outer:n
{
%  \seq_clear:N \l_tmpa_seq
  \seq_set_split:Nnn \l_tmpa_seq { ; }{#1}

%\seq_use:Nnnn \l_tmpa_seq{,}{,}{,} % EXPECT a,b,c % OK

%\seq_map_inline:Nn \l_tmpa_seq{(##1)} % EXPECT (a)(b)(c) % OK

%wishful thinking?
  \exp_last_unbraced:Nf
  \__erw_inner:nnn
  {
    \seq_map_inline:Nn \l_tmpa_seq{\exp_not:n{{##1}}}
  }
} %WANT: \erw_inner:nnn{a}{b}{c} % GET: ERROR: You can't use a prefix with `the character )'

\NewDocumentCommand\Test{m}
{
  \__erw_outer:n{#1}
}

\begin{document}

\Test{a;b;c}

\ExplSyntaxOff
\end{document}

答案1

我不太明白你为什么要使用“辅助函数” \__erw_inner:nnn\__erw_outer:N但我认为这是你心中实际应用程序的一部分。在我看来,你误用了 expl3 语法:当你使用

\seq_set_split:Nnn \l_tmpa_seq { ; }{#1}

拆分输入,然后您可以\l_tmpa_seq使用 expl3 提供的工具处理数据。特别是,我不明白为什么您\exp_last_unbraced:Nf的代码中有这个。

为了获得所需的输出,您可以使用以下命令:

\documentclass{report}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand\Test{m}
{
  \seq_set_split:Nnn \l_tmpa_seq { ; }{#1} % split the input
  \seq_map_inline:Nn \l_tmpa_seq {(##1)}   % print bracket enclosed input 
}
\ExplSyntaxOff

\begin{document}

  \Test{a;b;c}

\end{document}

如果这不符合您的用例,您能否提供更多有关您真正想要做的事情的信息?

请注意,应将其\ExplSyntaxOff放在 expl3 宏定义的末尾。如果它位于文档末尾(如在 MWE 中),则所有特殊 expl3 字符都将无法在文档中使用。

答案2

不,你不是在尝试做该\SplitArgument做的事情。这个预处理器想要参数:一个数字和一个分隔符。数字是必需的。

如果你

\NewDocumentCommand{\test}{ >{\SplitArgument{2}{;}}m } {...#1...}

那么你可以相信它将#1被传递为支撑群。因此

\test{a;b;c}
\test{a;b}
\test{a}

将分别通过

{a}{b}{c}
{a}{b}{-NoValue-}
{a}{-NoValue-}{-NoValue-}

该论点不应是空洞的。

当然,替换文本\test将包含类似

...\Command#1...

其中\Command是一个包含三个参数的命令,它将测试每个参数是否-NoValue-通过测试\IfNoValueTF

如果参数\test包含两个以上的分号,则会出现错误,因为宏\Command无法合理地处理其后跟的四个括号组。

你的目标似乎更相似\SplitList。假设你有

\NewDocumentCommand{\test}{ >{\SplitList{;}}m } { ... }

那么替换文本应该包含类似

\ProcessList{#1}{\Command}

其中\Command是一个单参数宏,列表中的每个项目将依次传递给它。因此,例如,

\NewDocumentCommand{\test}{ >{\SplitList{;}}m }{%
  \ProcessList{#1}{\Command}%
}
\NewDocumentCommand{\Command}{m}{(#1)}

调用如下

\test{a;b;c;d;e}

将导致输出

(一)(二)(三)(四)(五)

分号分隔的项目数量没有限制,但参数不能为空。

例子

\documentclass{article}
\usepackage{xparse}

\NewDocumentCommand{\testA}{ >{\SplitArgument{2}{;}}m }{%
  \CommandA#1%
}
\NewDocumentCommand{\CommandA}{mmm}{%
  #1--%
  \IfNoValueTF{#2}{???}{#2}--%
  \IfNoValueTF{#3}{???}{#3}%
}

\NewDocumentCommand{\testB}{ >{\SplitList{;}}m }{%
  \ProcessList{#1}{\CommandB}%
}
\NewDocumentCommand{\CommandB}{m}{%
  (#1)%
}

\begin{document}

Here we look at \verb+\SplitArgument+

\testA{a;b;c}\par
\testA{a;b}\par
\testA{a}\par

\bigskip

Here we look at \verb+\SplitList+

\testB{a;b;c;d;e}\par
\testB{a;b;c;d}\par
\testB{a;b;c}\par
\testB{a;b}\par
\testB{a}\par

\end{document}

在此处输入图片描述


如果您想模仿后一种行为该怎么办?

\ExplSyntaxOn

\NewDocumentCommand{\test}{m}
 {
  \seq_set_split:Nnn \l_tmpa_seq { ; } { #1 }
  \seq_map_function:NN \l_tmpa_seq \__erwann_parens:n
 }

\cs_new:Nn \__erwann_parens:n { (#1) }

\ExplSyntaxOff

答案3

正如问题中给出的代码中所述,我想要\__erw_outer:n{a;b;c}输出\__erw_inner:nnn{a}{b}{c}需要类似 的内容\SplitArgument。我应该补充说,这样做的动机是为了能够对外部参数进行参数扩展。这是一个糟糕的解决方案,在expl3和之间来回切换xparse。一切都应该在expl3(也许\__xparse_split_argument:nnn?)

\documentclass{report}
\usepackage{xparse}

\ExplSyntaxOn

\cs_new:Nn \__erw_inner:nnn{(#1)(#2)(#3)}

\NewDocumentCommand\ErwOuter
  {> { \SplitArgument { 2 } { ; } } m }
{
  \__erw_inner:nnn#1
}

\cs_new:Nn \__erw_outer:n
{

\ErwOuter{#1}

} %WANT: \erw_inner:nnn{a}{b}{c} 

\cs_generate_variant:Nn \__erw_outer:n {e}

\NewDocumentCommand\Test{m}
{
  \tl_set:Nn \l_tmpa_tl{#1} 
  \__erw_outer:n{\l_tmpa_tl}\\
  \__erw_outer:e{\l_tmpa_tl}
}

\begin{document}

 \Test{a;b;c}

\ExplSyntaxOff
\end{document}

屏幕

相关内容