使用 pgffor 的 bmatrix 特征的 \newcommand 会引发缺失 \endgroup 错误

使用 pgffor 的 bmatrix 特征的 \newcommand 会引发缺失 \endgroup 错误

这个问题分为两部分。我主要想实现一个\newcommand可以接受任意数量的参数并将它们设置在矩阵的单个列中的函数。

我尝试了以下操作,但是它引发了缺失\endgroup错误(这似乎是的结果\\,因为取出\\可以消除错误,但没有达到预期的结果):

\documentclass{article}

\usepackage{pgffor}
\usepackage{amsmath}

\newcommand*{\Features}[1]{%
\(%
\begin{bmatrix}%
\foreach \entry in {#1} {\text{\entry}\\}
\end{bmatrix}%
\)%
}

\begin{document}

\Features{--ACC, +PL}

\end{document}

有没有简单的方法可以解决这个问题并使其按预期工作?

问题的第二部分是为什么发生了这种情况。出于学习目的以及为了将来能够编写更好的宏,我很好奇,但我一直无法弄清楚是什么导致了缺失错误\endgroup

答案1

Enrico Gregorio 已经在他的评论: \foreach将其循环主体放在一个组中。这与矩阵环境的单元分组相冲突。另一个问题是,如果行尾后有不可展开的内容(组尾、\relax……),则会创建一个新的(空)行。

下面使用循环来定义\MatrixBody包含矩阵行的。链\expandafter展开\entry一次。否则宏\MatrixBody将包含\entry每个矩阵行,循环后未定义。

全局赋值仅用于\g@addto@macro允许向宏添加内容的 LaTeX 内核。(局部变量由包定义,例如ltxcmds)。

\documentclass{article}

\usepackage{pgffor}
\usepackage{amsmath}

\makeatletter
\newcommand*{\Features}[1]{%
  \global\let\MatrixBody\@empty
  \foreach \entry in {#1} {%
    \expandafter\g@addto@macro\expandafter\MatrixBody
    \expandafter{%
      \expandafter\text\expandafter{\entry}\\%
    }%
  }%
  \(%
    \begin{bmatrix}%
      \MatrixBody
    \end{bmatrix}%
  \)%
}
\makeatother

\begin{document}

\Features{--ACC, +PL}

\end{document}

结果

答案2

问题是\foreach执行组中的每个循环。所以在你的情况下你基本上是在做

\(
\begin{bmatrix}
\begingroup\text{--ACC}\\\endgroup
\begingroup\text{+PL}\\\endgroup
\end{bmatrix}
\)

这确实停止了

! Missing \endgroup inserted.
<inserted text> 
                \endgroup 

您必须事先构建矩阵的内容。另外,使用不分组的循环过程无论如何都是一场失败的战斗,因为表格单元格也会按组进行评估并\\结束它。

这是一个expl3基于的宏。

\documentclass{article}

\usepackage{amsmath}
\usepackage{xparse}

\ExplSyntaxOn
% the user level command
\NewDocumentCommand{\Features}{ m }
 {
  \adam_features:n { #1 }
 }
% a variable
\seq_new:N \l_adam_items_seq
% the programmer level function
\cs_new_protected:Npn \adam_features:n #1
 {
  % clear the sequence
  \seq_clear:N \l_adam_items_seq
  % do a mapping on the comma list separated input
  % adding the item between \mathrm{ and }
  \clist_map_inline:nn { #1 }
   {
    \seq_put_right:Nn \l_adam_items_seq { \mathrm { ##1 } }
   }
  \(
  \begin{bmatrix}
  % deliver the items separated by \\
  \seq_use:Nn \l_adam_items_seq { \\ }
  \end{bmatrix}
  \)
}
\ExplSyntaxOff

\begin{document}

\Features{-ACC, +PL}

\end{document}

请注意,我使用\mathrm而不是\text;但这是个人选择。

在此处输入图片描述

答案3

pgffor我相信我已经找到了一种比目前给出的解决方案更简单的替代方案。它使用\forcsvlist来自etoolbox,这似乎不会受到中的分组问题的影响pgffor

\documentclass{minimal}

\usepackage{amsmath}
\usepackage{etoolbox}

\newcommand*{\textmatrixline}[1]{\text{#1}\\}
\newcommand*{\bigsqbr}[1]{%
  \(%
    \begin{bmatrix}%
      \forcsvlist{\textmatrixline}{#1}
    \end{bmatrix}%
  \)%
}

\begin{document}

\bigsqbr{--ACC, +PL}

\end{document}

在此处输入图片描述

相关内容