expl3:使用 \int_do_while 循环遍历一个序列

expl3:使用 \int_do_while 循环遍历一个序列

我有一个序列,我通过项目编号获取元素(这里没有显示宏所需的元素)。我试图在循环中迭代序列的元素,do_while但出现整数比较错误。我读了文档,interface3但找不到问题所在。

梅威瑟:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\DeclareDocumentCommand{\setlist}{}{
\seq_new:N \g_test_seq
\seq_gset_from_clist:Nn \g_test_seq {lin1, line2, line3} 
}

\DeclareDocumentCommand{\insertdata}{m}{
  \seq_item:Nn \g_test_seq #1
}


\DeclareDocumentCommand{\getitemswhile}{}{
  \int_new:N \l_test_count
  \int_set:Nn \l_test_count {\seq_count:N \g_test_seq}
  \int_set:Nn \l_tmpa_int {1}

  \int_do_while:nn {\l_tmpa_int < \l_test_count}
    {
    \insertdata{\int_use:N \l_tmpa_int}
    \int_incr:N \l_tmpa_int
    }
}

\ExplSyntaxOff


\begin{document}
\setlist
\getitemswhile
\end{document}

错误(运行 TexLive 2016 更新)显示:

? 
! You can't use `the character <' after \the.
<argument> <

l.34 \getitemswhile

? 
! Missing = inserted for \ifnum.
<to be read again> 
                   \__int_eval:w 
l.34 \getitemswhile

答案1

你的问题是

\seq_item:Nn \g_test_seq #1

你应该

\seq_item:Nn \g_test_seq { #1 }

无论如何,您可能想要解决的那些定义中都有用户界面和编程层的奇怪混合;此外,声明应该在命令之外;而且,您应该遵守命名约定(\l_test_int而不是\l_test_count)。

\documentclass{scrartcl}
\usepackage{xparse}

\ExplSyntaxOn

\seq_new:N \g_test_seq
\DeclareDocumentCommand \setlist { }
 {
  \seq_gset_from_clist:Nn \g_test_seq { lin1 , line2 , line3 }
 }

\DeclareDocumentCommand \insertdata { m }
 {
  \seq_item:Nn \g_test_seq { #1 }
 }

\int_new:N \l_test_int
\DeclareDocumentCommand \getitemswhile { }
 {
  \int_set:Nn \l_test_int { \seq_count:N \g_test_seq }
  \int_set:Nn \l_tmpa_int { 1 }
  \int_do_while:nn { \l_tmpa_int < \l_test_int }
   {
    \insertdata { \int_use:N \l_tmpa_int }
    \int_incr:N \l_tmpa_int
   }
 }

\ExplSyntaxOff


\begin{document}
\setlist
\getitemswhile
\end{document}

答案2

其中有几种工具expl3可以帮助完成某些任务。

仅在真正需要时使用\seq_item:Nn;用于做某事全部序列中有\seq_map_inline:Nn或项\seq_map_function:NN

Manuel 在他的回答中已经指出了代码中的一些问题;最主要的是变量的声明通常应该是外部宏/函数的定义。

当然可以在函数中声明变量,但只有当这些变量需要在运行时定义时才这样做,并且变量的名称取决于当前条件。

你也应该不是\DeclareDocumentCommand一般来说,使用:这将覆盖同一宏的任何先前的定义。

以下是\seq_map_inline:Nn

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\setlist}{m}
 {
  \seq_gset_from_clist:Nn \g_textnik_test_seq { #1 }
 }

\NewDocumentCommand{\getitems}{}
 {
  \seq_map_inline:Nn \g_textnik_test_seq
   {
    ##1\par
   }
 }
\seq_new:N \g_textnik_test_seq
\ExplSyntaxOff

\begin{document}

\setlist{line1, line2, line3}

\getitems

\end{document}

您可以看到当前项被传递给映射部分#1(这里##1,因为我们在定义中)。您可以对它做任何您想做的事情,甚至可以将它作为参数传递给另一个宏。

同样\seq_map_function:NN

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\setlist}{m}
 {
  \seq_gset_from_clist:Nn \g_textnik_test_seq { #1 }
 }

\NewDocumentCommand{\getitems}{}
 {
  \seq_map_function:NN \g_textnik_test_seq \textnik_dopar:n
 }
\seq_new:N \g_textnik_test_seq
\cs_new_protected:Nn \textnik_dopar:n
 {
  #1\par
 }
\ExplSyntaxOff

\begin{document}

\setlist{line1, line2, line3}

\getitems

\end{document}

在这种情况下,每个项目都作为参数传递给指示的一个参数函数。

在此处输入图片描述

您也可以添加计数器:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\setlist}{m}
 {
  \seq_gset_from_clist:Nn \g_textnik_test_seq { #1 }
 }

\NewDocumentCommand{\getitems}{}
 {
  \int_zero:N \l_textnik_test_int
  \seq_map_inline:Nn \g_textnik_test_seq
   {
    \int_incr:N \l_textnik_test_int
    \int_to_arabic:n {\l_textnik_test_int}:~##1\par
   }
 }
\seq_new:N \g_textnik_test_seq
\int_new:N \l_textnik_test_int
\ExplSyntaxOff

\begin{document}

\setlist{line1, line2, line3}

\getitems

\end{document}

相关内容