\seq_push 和 \seq_pop 函数行为异常,无疑是由于误用造成的

\seq_push 和 \seq_pop 函数行为异常,无疑是由于误用造成的

出于我自己的充分理由,我加载了\param_seq一个参数数组,然后想通过弹出\param_seq将的内容传输到,将弹出的项目暂时存储在中,然后推送到 。经过两次弹出和推送循环后,我已经看到事情出了问题;由于某种原因,最后弹出的项目的副本数与循环数一样多,现在没有丢失弹出的项目,而是用最后弹出的副本替换了它们。这不是人们对一对堆栈所期望的那种恶作剧。我做错了什么?我应该补充一点,在实际操作中,我对不同的参数做了不同的事情,因此有 case 子句。\aux_seq\param_seq\aux_tl\aux_tl\aux_seq\aux_seq\param_seq

\documentclass{minimal}
%-----------------------------
\usepackage{xparse}
\usepackage{amsmath}
%=============================
\ExplSyntaxOn
\tl_new:N \output_tl
\tl_new:N \aux_tl
\seq_new:N \params_seq
\seq_new:N \aux_seq
\int_new:N \index_i
%-----------------------------
\NewDocumentCommand\myFunction{O{,} m}{\myFunction_build:nn {#1}{#2}}
  \cs_new:Npn \myFunction_build:nn #1 #2 
    {
    \tl_clear:N \output_tl 
    \seq_clear:N \params_seq 
    \seq_set_split:Nnn \params_seq { #1 } { #2 }
    \seq_pop_left:NN \params_seq \aux_tl
    \tl_use:N \aux_tl \\
    \seq_push:Nn \aux_seq \aux_tl
    \seq_pop_left:NN \params_seq \aux_tl
    \tl_use:N \aux_tl \\
    \seq_push:Nn \aux_seq \aux_tl 
    \int_set:Nn \index_i { 0 }
    \seq_map_inline:Nn \aux_seq 
      {
      \int_incr:N \index_i
      \int_case:nnTF {\index_i}
        {
                    {1} {\tl_put_right:Nn \output_tl {##1,\c_space_tl}}
                    {2} {\tl_put_right:Nn \output_tl {##1,\c_space_tl}}
                    {3} {\tl_put_right:Nn \output_tl {##1,\c_space_tl}}
                    {4} {\tl_put_right:Nn \output_tl {##1,\c_space_tl}}
        }
        {}
        {}
      }
    \text{contents\, of\, aux\, sequence\,after\,two\,pushes:\, } \tl_use:N \output_tl \\
    \int_set:Nn \index_i { 0 }
    \seq_map_inline:Nn \params_seq  
      {
      \int_incr:N \index_i
      \int_case:nnTF {\index_i}
        {
                    {1} {\tl_put_right:Nn \output_tl {##1,\c_space_tl}}
                    {2} {\tl_put_right:Nn \output_tl {##1,\c_space_tl}}
                    {3} {\tl_put_right:Nn \output_tl {##1,\c_space_tl}}
                    {4} {\tl_put_right:Nn \output_tl {##1,\c_space_tl}}
        }
        {}
        {}
      }
    \text{contents\, of\, params\, seq\,after\,two\,pops:\, } \tl_use:N \output_tl \\
    }
\ExplSyntaxOff
%=======================================
\begin{document}
\noindent
\textbf{Function call:} \verb+\myFunction{1,2,3,4,5}+\\
\textbf{Disappointing result:} \\
\myFunction{1,2,3,4,5}\\
\end{document} 

答案1

除了变量命名方案不当之外,问题还在于误用了\seq_push:Nn应该改为

\seq_push:NV \l_neuwirth_aux_seq \l_neuwirth_aux_tl

\seq_push:NV \l_neuwirth_aux_seq \l_neuwirth_aux_tl

因为你想推动内容变量的,而不是变量本身。我根据声明使用了“正确的”变量名

\tl_new:N \l_neuwirth_output_tl
\tl_new:N \l_neuwirth_aux_tl
\seq_new:N \l_neuwirth_params_seq
\seq_new:N \l_neuwirth_aux_seq
\int_new:N \l_neuwirth_index_int

完整代码。另请注意

  1. 内部函数的命名
  2. protected
  3. \int_case:nn而不是\int_case:nnTF使用空的参数
  4. ~输出中的空格
  5. \seq_pop:NN在将序列用作堆栈的情况下是首选:顶部是“左侧”这一事实不应引起关注。
\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\tl_new:N \l_neuwirth_output_tl
\tl_new:N \l_neuwirth_aux_tl
\seq_new:N \l_neuwirth_params_seq
\seq_new:N \l_neuwirth_aux_seq
\int_new:N \l_neuwirth_index_int

\NewDocumentCommand\myFunction{O{,} m}
 {
  \neuwirth_myfunction_build:nn {#1}{#2}
 }

\cs_new_protected:Npn \neuwirth_myfunction_build:nn #1 #2 
 {
  \tl_clear:N \l_neuwirth_output_tl 
  \seq_clear:N \l_neuwirth_params_seq 
  \seq_set_split:Nnn \l_neuwirth_params_seq { #1 } { #2 }
  \seq_pop:NN \l_neuwirth_params_seq \l_neuwirth_aux_tl
  \tl_use:N \l_neuwirth_aux_tl \\
  \seq_push:NV \l_neuwirth_aux_seq \l_neuwirth_aux_tl
  \seq_pop:NN \l_neuwirth_params_seq \l_neuwirth_aux_tl
  \tl_use:N \l_neuwirth_aux_tl \\
  \seq_push:NV \l_neuwirth_aux_seq \l_neuwirth_aux_tl 
  \int_set:Nn \l_neuwirth_index_int { 0 }
  \seq_map_inline:Nn \l_neuwirth_aux_seq 
   {
    \int_incr:N \l_neuwirth_index_int
    \int_case:nn {\l_neuwirth_index_int}
     {
      {1} {\tl_put_right:Nn \l_neuwirth_output_tl {##1,~}}
      {2} {\tl_put_right:Nn \l_neuwirth_output_tl {##1,~}}
      {3} {\tl_put_right:Nn \l_neuwirth_output_tl {##1,~}}
      {4} {\tl_put_right:Nn \l_neuwirth_output_tl {##1,~}}
     }
   }
  \mbox{contents~of~aux~sequence~after~two~pushes:~} \tl_use:N \l_neuwirth_output_tl \\
  \int_set:Nn \l_neuwirth_index_int { 0 }
  \seq_map_inline:Nn \l_neuwirth_params_seq  
   {
    \int_incr:N \l_neuwirth_index_int
    \int_case:nn {\l_neuwirth_index_int}
     {
      {1} {\tl_put_right:Nn \l_neuwirth_output_tl {##1,~}}
      {2} {\tl_put_right:Nn \l_neuwirth_output_tl {##1,~}}
      {3} {\tl_put_right:Nn \l_neuwirth_output_tl {##1,~}}
      {4} {\tl_put_right:Nn \l_neuwirth_output_tl {##1,~}}
     }
   }
  \mbox{contents~of~params~seq~after~two~pops:~} \tl_use:N \l_neuwirth_output_tl \\
 }
\ExplSyntaxOff

\begin{document}

\noindent
\textbf{Function call:} \verb+\myFunction{1,2,3,4,5}+\\
\textbf{Disappointing result:} \\
\myFunction{1,2,3,4,5}

\end{document} 

在此处输入图片描述

与所说的相反,结果应该不会再令人失望了。

实际上,您使用了错误的方法来显示序列;这里有一些可以正确执行的操作的代码:

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\tl_new:N \l_neuwirth_aux_tl
\seq_new:N \l_neuwirth_params_seq
\seq_new:N \l_neuwirth_aux_seq

\NewDocumentCommand\myFunction{O{,} m}
 {
  \neuwirth_myfunction_build:nn {#1}{#2}
 }

\cs_new_protected:Npn \neuwirth_myfunction_build:nn #1 #2 
 {
  \seq_set_split:Nnn \l_neuwirth_params_seq { #1 } { #2 }
  \seq_pop:NN \l_neuwirth_params_seq \l_neuwirth_aux_tl
  \tl_use:N \l_neuwirth_aux_tl \\
  \seq_push:NV \l_neuwirth_aux_seq \l_neuwirth_aux_tl
  \seq_pop:NN \l_neuwirth_params_seq \l_neuwirth_aux_tl
  \tl_use:N \l_neuwirth_aux_tl \\
  \seq_push:NV \l_neuwirth_aux_seq \l_neuwirth_aux_tl 
  \mbox{contents~of~aux~sequence~after~two~pushes:~} \seq_use:Nn \l_neuwirth_aux_seq {,~}\\
  \mbox{contents~of~params~seq~after~two~pops:~} \seq_use:Nn \l_neuwirth_params_seq {,~}\\
 }
\ExplSyntaxOff

\begin{document}

\noindent
\textbf{Function call:} \verb+\myFunction{1,2,3,4,5}+\\
\textbf{Expected result:} \\
\myFunction{1,2,3,4,5}

\end{document} 

在此处输入图片描述

相关内容