如何创建带有逗号分隔参数列表的递归 Latex 宏

如何创建带有逗号分隔参数列表的递归 Latex 宏

我想创建一个宏,它接受两个参数,第二个参数是一个逗号分隔的列表,然后使用参数 2 的每个条目生成参数 1 的嵌套交换器。我一直试图通过循环遍历参数 2 中的值并递归调用一个简单的交换器宏来实现这一点,但我一直收到以下错误:

! TeX capacity exceeded, sorry [grouping levels=255].

我尝试使用etoolboxdocsvlist但不知道如何让它做我想做的事情。

看起来好像我遇到了无限循环,或者我的 def 方案存在一些问题,但我不知道它是什么。

详细信息:
基本换向器宏:

\newcommand{\commut}[2]{\left[{#1},{#2}\right]}

强力嵌套交换器:

\newcommand{\qcommut}[5]{\commut{\commut{\commut{\commut{#1}{#2}}{#3}}{#4}}{#5}}

尝试自动化版本:

\makeatletter
\newcommand{\ncommut}[2]{
  \def\mainArg{#1}
  \newcommand{\argList}{#2}
  \@for\i:=\argList\do{
    \def\mainArg{
      \commut{\mainArg}{\i}
    }
  }
}
\makeatother

我可以调用\commut\qcommut,但\ncommut会产生错误。

\begin{equation}
  \commut{A}{B}
  \qcommut{A}{B}{C}{D}{E}
  \ncommut{A}{B,C,D,E} % desired usage
\end{equation}

期望输出:

期望输出

答案1

这是一个不同的 LaTeX3 实现,它也允许嵌套调用:

\documentclass{article}
\usepackage{xparse,mleftright}
\ExplSyntaxOn
\NewDocumentCommand{\commut}{ m }
 {
  \group_begin: \mactay_commut:n { #1 } \group_end:
 }
\cs_new_protected:Npn \mactay_commut:n #1
 {
  \seq_set_from_clist:Nn \l__mactay_list_seq { #1 }
  \int_compare:nTF { \seq_count:N \l__mactay_list_seq = 1 }
   { #1 } % only one element
   { % more than one element
    % detach the first element
    \seq_pop_left:NN \l__mactay_list_seq \l__mactay_first_tl
    % add as many \mleft[ as needed
    \prg_replicate:nn { \seq_count:N \l__mactay_list_seq }
     { \mleft[ }
    % put the first element and a comma
    \tl_use:N \l__mactay_first_tl ,
    % deliver all the other elements, followed by \mright] and a comma
    \seq_use:Nnnn \l__mactay_list_seq { \mright] , } { \mright] , } { \mright] , }
    % final \mright]
    \mright]
   }
 }
\seq_new:N \l__mactay_list_seq
\tl_new:N \l__mactay_first_tl
\ExplSyntaxOff

\begin{document}

$\commut{A}$

$\commut{A,B}$

$\commut{A,B,C}$

$\commut{A,B,C,D}$

$\commut{\commut{A,B},\commut{C,D}}$

\end{document}

在此处输入图片描述

答案2

在此处输入图片描述

\documentclass{article}
\newcommand{\commut}[2]{\left[{#1},{#2}\right]}

\makeatletter
\def\qcommut#1{\xcommut#1,\relax,}
\def\xcommut#1,{\xxcommut{#1}}
\def\xxcommut#1#2,{%
\ifx\relax#2%
#1%
\expandafter\@gobbletwo
\fi
\xxcommut{\commut{#1}{#2}}}

\begin{document}

$\qcommut{1,2,3,4,5,6}$
\end{document}

答案3

还有一个用于kvsetkeys解析逗号分隔列表的解决方案。\qcommut定义包含未扩展参数的\commut@list嵌套调用:\commut

\documentclass{article}
\usepackage{kvsetkeys}
\usepackage{etexcmds}

\makeatletter
\newcommand*{\commut}[2]{\left[{#1},{#2}\right]}
\newcommand*{\qcommut}[1]{%
  \let\commut@list\relax
  \comma@parse{#1}\@qcommut
  \typeout{\meaning\commut@list}% for debugging
  \commut@list
}
\def\@qcommut#1{%
  \ifx\commut@list\relax
    \def\commut@list{#1}%
  \else
    \edef\commut@list{%
      \noexpand\commut{%
        \etex@unexpanded\expandafter{\commut@list}%
      }{#1}%
    }%
  \fi
}
\makeatother

\begin{document}
\[ \qcommut{A,B,C,D,E} \]
\end{document}

\comma@list

macro:->\commut {\commut {\commut {\commut {A}{B}}{C}}{D}}{E}

结果

答案4

这是一个快速的expl3解决方案(前提是我理解正确)。

在此处输入图片描述

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand {\ncommut} { m m }
    {
        \n_commut:nn {#1}{#2}
    }

\cs_new:Npn \n_commut:nn #1#2
    {
        \tl_set:Nn \l_tmpa_tl {#1}
        \clist_map_inline:nn {#2}
            {
                \tl_set:Nx \l_tmpa_tl {\__n_commut_aux:Vn \l_tmpa_tl {##1}}
            }
        \tl_use:N \l_tmpa_tl
    }

\cs_new:Npn \__n_commut_aux:Vn #1#2
    {
        \left[{#1},{#2}\right]
    }

\ExplSyntaxOff
\begin{document}

$\ncommut{1}{2,3,4,5}$

$\ncommut{a}{b,c,d,e,f,g}$

\end{document}

相关内容