序列LaTeX3
很难理解。我正在编写一些小演示来尝试学习各种命令。在这个演示中,我可以输入一个序列然后打印它。但是,当我在序列周围加上括号时,只有第一个元素的第一个字母被括起来。如果我使用,\seq_set_from_clist:NN
输出就更奇怪了,括号里什么都没有显示。我显然不明白什么?
这是我的 MWE 和编译的输出。
\documentclass[10pt]{article}
\usepackage{expl3,xparse}
\ExplSyntaxOn
\seq_new:N \l_demo_myseq_seq
\cs_new_protected:Npn \demo_inputseq:n #1
{%
% get a sequence
\seq_set_eq:NN \l_demo_myseq_seq #1
%\seq_set_from_clist:NN \demo_myseq_seq #1
Forward~sequence~is~(\l_demo_myseq_seq)
}%
\NewDocumentCommand{\getasequence}{ m }
{%
\demo_inputseq:n #1
}%
\ExplSyntaxOff
\begin{document}
\getasequence{red, orange, cyan}
\end{document}
答案1
在 expl3 中,用小写字母表示的参数(n、o、f、x、c 等)始终需要括号。因此您\getasequence
不应使用\demo_inputseq:n #1
but \demo_inputseq:n { #1 }
。(这导致了您遇到的实际问题:由于缺少括号,只有第一个标记被传递。
此外,\seq_set_eq:NN
仅当您已经在序列变量中存储了序列时才应使用。但是您只有一个逗号分隔的列表,该列表作为参数传递,而不是存储在变量中,因此您需要\seq_from_clist:Nn
(小写n
表示您不想传递变量。)此外,您需要指定应以哪种形式输出列表。在您的情况下,\seq_use:Nn
可能合适:它使用给定的分隔符打印条目:
\documentclass[10pt]{article}
\usepackage{expl3,xparse}
\ExplSyntaxOn
\seq_new:N \l_demo_myseq_seq
\cs_new_protected:Npn \demo_inputseq:n #1
{%
% get a sequence
\seq_set_from_clist:Nn \l_demo_myseq_seq {#1}
Forward~sequence~is~(\seq_use:Nn \l_demo_myseq_seq {,})
}%
\NewDocumentCommand{\getasequence}{ m }
{%
\demo_inputseq:n {#1}
}%
\ExplSyntaxOff
\begin{document}
\getasequence{red, orange, cyan}
\end{document}
答案2
更多细节。
TeX 在宏定义和参数扫描方面总是相同的。
例如,序列是带有特制替换文本的宏。如果我们将和a
存储在序列中,我们就会执行b
c
\l_tmpa_seq
\show \l_tmpa_seq
我们看
> \l_tmpa_seq=macro:->\s__seq \__seq_item:n {a}\__seq_item:n {b}\__seq_item:n {c}.
控制序列\s__seq
只是一个别名\relax
,宏\__seq_item:n
会发出一个错误消息(当在错误的上下文中使用序列时,这是相关的)。
这两个控制序列被用作以下功能的标记:使用序列,例如\seq_map_inline:Nn
或\seq_use:Nn
和应该绝不除团队定义程序员级别的功能外,还可使用。
您定义的函数
\cs_new_protected:Npn \demo_inputseq:n #1
接受一个参数,但是当你调用它时,参数应该被括起来(除非它只包含一个标记。因为你将它调用为
\demo_inputseq:n #1
并且该文件有
\getasequence{red, orange, cyan}
TeX 会看到
\demo_inputseq:n red, orange, cyan
参数为r
。这部分解释了输出
(r)ed、橙色、青色
但并非全部。现在发生的是,这个输入被转换成
\seq_set_eq:NN \l_demo_myseq_seq r Forward~sequence~is~(\l_demo_myseq_seq)ed, orange, cyan
该\seq_set_eq:NN
功能(当前)已实现\let
,这就是为什么您的错误输入不会发出实际错误消息的原因。
带有签名的函数:NN
需要两个无括号的单个标记参数,但不可能执行如果这样做
\seq_set_eq:NN \foo { abc }
根据实际实现,这可能会产生错误,也可能不会。但是,文档说应该\seq_set_eq:NN
跟两个序列变量名,并且第一个序列将(局部)与第二个序列相同。因此,第一个变量应该以\l_
(或\l__
)开头,而第二个变量可以是局部的、全局的或常量的。
正如 Marcel 所写,你可以使用
\seq_set_from_clist:Nn \l_demo_myseq_seq { #1 }
但是也
\seq_set_split:Nnn \l_demo_myseq_seq { , } { #1 }
不同之处在于前者会忽略“空”项目,而后者则不会。例如
\seq_set_from_clist:Nn \l_tmpa_seq { a, , c }
\seq_show:N \l_tmpa_seq
产量
The sequence \l_tmpa_seq contains the items (without outer braces):
> {a}
> {c}.
然而
\seq_set_split:Nnn \l_tmpa_seq { , } { a, , c}
\seq_show:N \l_tmpa_seq
会产生
The sequence \l_tmpa_seq contains the items (without outer braces):
> {a}
> {}
> {c}.
忽略项前后的空格。选择哪种策略取决于实际需要。