我有一个命令可以容易地xparse
使用、etoolbox
和 等多种资源进行编写pgffor
。
\documentclass{article}
\usepackage{amsmath}
\usepackage{etoolbox}
\usepackage{xparse}
\usepackage{pgffor}
\makeatletter
\def\ae@tmp@frontmatter{}
\def\ae@list{}
\NewDocumentCommand\qchoice{ mom }
{%%
\def\ae@tmp@frontmatter{#2}
\let\ae@list\relax
\foreach \myn in {#3}
{%%
\ifx\ae@list\relax
\xdef\ae@list{\noexpand#1{\expandonce\ae@tmp@frontmatter\expandonce\myn}}%%
\else
\xdef\ae@list{\expandonce\ae@list
\noexpand\par
\noexpand#1{\expandonce\ae@tmp@frontmatter\expandonce\myn}}%%
\fi
}%%
\ae@list}
\makeatother
\newcommand\aebf[1]{$\rightarrow$ \textbf{#1} DONE}
\pagestyle{empty}
\begin{document}
\qchoice\aebf[front matter::]{a,b,c,d}
\end{document}
但是,我希望能够使用Expl3
语法编写与上述相同的代码。(除其他外,将\makeatletter
与xparse
just 结合使用似乎从哲学上来说错误的。)
看来我应该能够做到这一点,而不必使用pgffor
或etoolbox
。但我一直遇到问题。
这是我最近的尝试:
\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}
\ExplSyntaxOn
\tl_new:N \l_qchoice_command_sequence_tl
\tl_new:N \l_qchoice_front_matter_tl
\tl_new:N \l_qchoice_csv_choices_tl
\tl_new:N \l_qchoice_tmp_tl
\seq_new:N \l_qchoice_choices_seq
\NewDocumentCommand\qchoice{ mom }
{%%
\tl_set:Nn \l_qchoice_command_sequence_tl {#1}
\tl_clear:N \l_qchoice_front_matter_tl
\tl_clear:N \l_qchoice_csv_choices_tl
\IfNoValueF{#2}
{
\tl_set:Nn \l_qchoice_front_matter_tl {#2}
}
\seq_set_split:Nnn \l_qchoice_choices_seq {,} {#3}
\seq_map_function:NN \l_qchoice_choices_seq \qchoice_parse_choices:n
\l_qchoice_csv_choices_tl
}
\cs_new:Npn \qchoice_parse_choices:n #1
{
\tl_clear:N \l_qchoice_tmp_tl
\tl_set:No \l_qchoice_tmp_tl \l_qchoice_front_matter_tl
\tl_put_right:Nn \l_qchoice_tmp_tl {#1}
\tl_set:No \l_qchoice_tmp_tl {{\l_qchoice_tmp_tl}}
\tl_put_left:Nn \l_qchoice_tmp_tl \l_qchoice_command_sequence_tl
\tl_if_empty:NTF \l_qchoice_csv_choices_tl
{
\tl_set:No \l_qchoice_csv_choices_tl \l_qchoice_tmp_tl
}
{
\tl_put_right:Nn \l_qchoice_csv_choices_tl {\par}
\tl_put_right:No \l_qchoice_csv_choices_tl {\l_qchoice_tmp_tl}
}
}
\ExplSyntaxOff
\newcommand\aebf[1]{$\rightarrow$ \textbf{#1} DONE}
\pagestyle{empty}
\begin{document}
\qchoice\aebf[front matter::]{a,b,c,d}
\end{document}
线路似乎有问题
\tl_set:No \l_qchoice_tmp_tl {{\l_qchoice_tmp_tl}}
导致超出 TeX 容量错误。但语法对我来说似乎没问题,因为\l_qchoice_tmp_tl
应该扩展一次,然后将其内容分配回\l_qchoice_tmp_tl
。但这似乎不是正在发生的事情。
代码Expl3
似乎变得非常复杂,如果这仅仅是因为我限制自己只使用LaTeX3
资源,那么这没问题。
更新
最终我想要做的是
\qchoices<control sequence>[<optional front matter>]{<item a>,<item b>,<item c>,<item d>}
会产生一串像
<control sequence>{<optional front matter><item a>}<inter-item matter>
<control sequence>{<optional front matter><item b>}<inter-item matter>
<control sequence>{<optional front matter><item c>}<inter-item matter>
<control sequence>{<optional front matter><item d>}
在上面的例子中,我将其用作\par
我的<inter-item matter>
。请注意,<inter-item matter>
不应跟在传递的最后一项之后。
我在使用Expl3
代码时遇到的困难是将要传递的内容括<control sequence>
在括号中。
答案1
虽然您可以一次构建一部分结果,但我会安排x
使用映射在 -type 扩展中完成整个工作。由于输入是逗号列表,因此直接执行此操作可能最容易
\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}
\ExplSyntaxOn
\tl_new:N \l_qchoice_choices_tl
\cs_new:Npn \__qhoice_tmp:n #1 { }
\NewDocumentCommand \qchoice { m o m }
{
\tl_clear:N \l_qchoice_csv_tl
\cs_set:Npn \__qhoice_tmp:n ##1
{
\exp_not:N #1
{
\IfNoValueF {#2} { \exp_not:n {#2} }
\exp_not:n {##1}
}
\exp_not:N \par
}
\tl_set:Nx \l_qchoice_csv_tl
{
\clist_map_function:nN {#3}\__qhoice_tmp:n
}
\tl_show:N \l_qchoice_csv_tl
}
\ExplSyntaxOff
\newcommand\aebf[1]{$\rightarrow$ \textbf{#1} DONE}
\pagestyle{empty}
\begin{document}
\qchoice\aebf[front matter::]{a,b,c,d}
\end{document}
如果您不希望分隔符出现在最后一项之后,有几种方法。概念上最简单的方法可能是使用内联映射,其中有一个测试来查看列表是否为空:在这种情况下,不要添加分隔符。
\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}
\ExplSyntaxOn
\tl_new:N \l_qchoice_choices_tl
\cs_new:Npn \__qhoice_tmp:n #1 { }
\NewDocumentCommand \qchoice { m o m }
{
\tl_clear:N \l_qchoice_csv_tl
\clist_map_inline:nn {#3}
{
\tl_set:Nx \l_qchoice_csv_tl
{
\exp_not:V \l_qchoice_csv_tl
\tl_if_empty:NF \l_qchoice_csv_tl
{ \exp_not:N \par }
\exp_not:N #1
{
\IfNoValueF {#2} { \exp_not:n {#2} }
\exp_not:n {##1}
}
}
}
\tl_show:N \l_qchoice_csv_tl
}
\ExplSyntaxOff
\newcommand\aebf[1]{$\rightarrow$ \textbf{#1} DONE}
\pagestyle{empty}
\begin{document}
\qchoice\aebf[front matter::]{a,b,c,d}
\end{document}
这种方法需要每个项目分配一个任务:如果需要更高的效率,那么还有其他选择(问题表明列表很短)。
正如评论中所述,\tl_set:No \l_tmpa_tl { { \l_tmpa_tl } }
尝试扩展{
不\l_tmpa_tl
(\tl_set:No
处于较低级别并相当于\exp_after:wN \tl_set:Nn \exp_after:wN
)。通常,如果您可以使用 -type 扩展一次性完成工作,最好避免一次构建复杂的标记列表x
:只需要一次分配,这可以提高性能。