理解 \@for 循环

理解 \@for 循环

我在\@for循环方面遇到了麻烦。我有一个宏,它接受逗号分隔的列表并将每个元素放入数组的一行中。当我使用循环执行此操作时\@for,我得到了一个我无法理解的额外行。我可以用负空格手动将其删除(如下面的注释行所示),但这不是正确的方法,所以我一定是做错了什么。这是一个最小的例子。为了进行比较,如果我手动构建我期望的循环结果,则不会出现额外的行。

\documentclass{article}
\usepackage{amsmath}
\makeatletter
\newcommand{\fbun}[1]
   {\ensuremath{\left[\begin{array}{c}
      \@for\xx:=#1\do {\text{\xx}\\}
%     \\ [-2.75ex] % why is this required?
      \end{array}\right]}}
\makeatother
\begin{document}
$\left[\begin{array}{c}
      A\\
      B\\
      C\\
      D\\
      \end{array}\right]$
% same array, but generated by a macro
\fbun{A,B,C,D}
\end{document}

代码输出

答案1

正如 Altermundus 所说,您不能在 的最后一行之后添加额外的{}或其他不可见的材料。但是, 之后添加了一些额外的材料。 的实现对此不太好。\relaxtabular\@for\@for

由于\@forLaTeX2e 内核有限制,我建议\forcsvlistetoolbox

\documentclass{article}
\usepackage{amsmath}
\usepackage{etoolbox}
\def\addrow#1{\text{#1}\\}
\newcommand{\fbun}[1]
   {\ensuremath{\left[\begin{array}{c}
      \forcsvlist\addrow{#1}%
      \end{array}\right]}}

\begin{document}
$\left[\begin{array}{c}
      A\\
      B\\
      C\\
      D\\
      \end{array}\right]$

\fbun{A,B,C,D}
\end{document}

答案2

在《用户指南和参考手册》第 45 页中,Leslie Lamport 写道:

&一行中的最后一项之后必须没有,并且\\最后一行之后也必须没有 。

$\left[\begin{array}{c}
      A\\
      B\\
      C\\
      D\\{}%
\end{array}\right]$  

此代码给出一个带有空组的新行。数组的每个单元格都位于一个组中。

\@for是所以no developable loop你需要写类似

\fbun{A,B,C} 
D

或者您可以创建一个developable loop但它更复杂:

\makeatletter
\newcommand*{\For}[1]{\noalign{\gdef\@Do##1{#1}}\@For}
\newcommand*{\@For}[3]{%
  \unless\ifnum#1 \ifnum#3>0 >\else <\fi #2
    \@Do{#1}%
    \expandafter\@For\expandafter{\number\numexpr#1+#3}{#2}{#3}%
  \fi
} 
\makeatother

$\left[\begin{array}{c}
  \For{\@Alph{#1}\\}{1}{4}{1}    
\end{array}\right]$ 

\For例如developable loop,您可以尝试:

\begin{tabular}{ll}
  \For{A number & #1\\}{1}{20}{1}
\end{tabular}

答案3

问题是 TeX 在最后一个之后发现了一些\\开始新行的东西(它既不是\noalign也不\crcr是不会)。

一种解决方案可能是使用令牌寄存器:我​​们在第一个单元格中开发循环,因此\xx在 TeX 看到\\(或&)之后就不会出现不再定义的问题。

\usepackage{amsmath}
\makeatletter
\newcommand{\fbun}[1]{%
  \begin{bmatrix}
  \toks@={\@gobble}%
  \@for\next:=#1\do
    {\toks@=\@xp{\the\@xp\toks@\@xp\\\@xp\text\@xp{\next}}}%
  \the\toks@
  \end{bmatrix}}
\makeatother

我用过\@xp(从数学)是 的简写\expandafter;如果\text条目周围不需要,那么

\toks@=\expandafter{\the\expandafter\toks@\next}

就足够了。初始化\toks@\@gobble的效果是第一个\\被吞噬。

我已经array使用了bmatrix(如果愿意,可以更改它),当然,我\ensuremath第一步就删除了。:)

2023 年更新

我们可以利用工具让解决方案变得更简短、更易于理解expl3

\documentclass{article}
\usepackage{amsmath}

\ExplSyntaxOn

\NewDocumentCommand{\fbun}{O{c}m}
 {
  \ensuremath
   {
    \left[
    \begin{tabular}{#1}
    \clist_use:nn { #2 } { \\ }
    \end{tabular}
    \right]
   }
 }

\ExplSyntaxOff

\begin{document}

$\left[\begin{array}{c}
      \text{A}\\
      \text{B}\\
      \text{C}\\
      \text{D}\\
      \end{array}\right]$
% same array, but generated by a macro
\fbun{A,B,C,D}
\fbun[l]{Aaa,Bbbbbb,Cc,Dddd}

\end{document}

在此处输入图片描述

答案4

\ekvcsvloop使用提供的解决方案expkv。我还添加了一个小的 key=value 接口expkv-cs,支持的键是alignformatter(后者将获取每行的文本作为参数)。key=value 接口中还有一些快捷方式,cis align=clis align=lris align=r,并且每个没有 =value 的未知键都被视为格式化程序。

\documentclass{article}
\usepackage{amsmath}
\usepackage{expkv-cs}

\makeatletter
\newcommand\fbun[1][]{\fbun@kv{#1}}
% this is the output, if you don't need the bling bling of a key=value interface
% you can reduce the \fbun definition to this.
% With the current definition it'll get two arguments from \fbun@kv and as an
% additional argument reads the comma separated list.
\newcommand\fbun@out[3]
  {%
    \left[\begin{array}{#1}
      % ekvcsvloop will result in `\\#2{<#3-element>}` for each element in the
      % csv-list #3 (thanks to \expanded in a single step), `\@gobble` will
      % remove the first `\\`.
      \expandafter\@gobble\expanded{\ekvcsvloop{\\#2}{#3}}%
    \end{array}\right]%
  }
\ekvcSplitAndForward\fbun@kv\fbun@out
  {
    % the two keys that will correspond to an argument for \fbun@out
     align     = c
    ,formatter = \@firstofone
  }
\ekvcSecondaryKeys\fbun@kv
  {
    % in expkv it is documented behaviour that multiple equals signs are
    % allowed, the first is the one separating key from value
    % `nmeta` defines the following name to be a shortcut to set whatever is
    % specified in the value.
     nmeta c = align=c
    ,nmeta l = align=l
    ,nmeta r = align=r
  }
\ekvdefunknownNoVal{\string\fbun@kv}{\ekvcPass\fbun@kv{formatter}{#2}}
\makeatother

\begin{document}
$\fbun[\text]{Abc,B,C,D}$
$\fbun[c,\text]{Abc,B,C,D}$
$\fbun[l,\text]{Abc,B,C,D}$
$\fbun[r,\text]{Abc,B,C,D}$
$\fbun{ab,c,d}$
$\fbun[align=@{}c@{}]{ab,c,d}$
\end{document}

在此处输入图片描述

相关内容