为什么序列周围的括号没有包围整个序列?

为什么序列周围的括号没有包围整个序列?

序列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 #1but \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存储在序列中,我们就会执行bc\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}.

忽略项前后的空格。选择哪种策略取决于实际需要。

相关内容