无法在具有可选参数的用户定义命令中使用 & 符号作为参数

无法在具有可选参数的用户定义命令中使用 & 符号作为参数

我正在尝试为一个方程生成一个命令,该命令可能在元素内部使用,也可能不在元素内部使用align,因此有时需要&在旁边=对齐方程。因此,我定义了该命令\newcommand{\optal}[1][=]{a #1 b},以便当调用为简单时\optal它会输出方程,但当调用为时,\optal[&=]我可以在对齐中使用方程。问题是,由于某种原因,命令失败;似乎不能用作&参数。如果我将参数设为强制参数(即\newcommand{\optal}[1]{a #1 b}) ,问题就会消失)

这是 MWE。我使用的是 Miktex 2.9 和 pdflatex。

    \documentclass[a4paper, 12pt]{book}
    \usepackage{amssymb}
    \usepackage{amsmath}

    \begin{document}
    % new command
    \newcommand{\optal}[1][=]{a #1 b}
    %trying it out
    $\optal$ \\
    $\optal[ \neq ]$ \\
    % trying it out inside align
    \begin{align}
    \optal[=]
    \end{align}
    %so far, so good
    % trying it out with & as parameter
    \begin{align}
    \optal[&=]
    \end{align}
    % Fails with "Argument of \\optal has an extra } \end{align}"
    % Paragraph ended before \\optal was complete \end{align}
    \end{document}

我是不是漏掉了什么?你能想出解决办法吗?

答案1

用牙套保护它

\optal[{&=}]

请注意,您可以在等式的一边添加更多符号。

\documentclass{report}
\usepackage{amssymb}
\usepackage{amsmath}
\newcommand{\optal}[1][=]{a #1 b}

\begin{document}
$\optal$ 
$\optal[ \neq ]$ 
\begin{align}
\optal
\end{align}
\begin{align}
\optal[{&=}]         & \optal[{&=}] + \int \\
\optal[{&=}] + \iint & \optal[{&=}] - \partial
\end{align}
\end{document}

enter image description here

答案2

您发现了对齐过程中的一个黑暗角落。让我们看看会发生什么。

  1. 当在对齐中启动一个单元格时,TeX 会扩展标记以查看是否\omit出现(例如,它用于\multicolumn跨越列)。

  2. 的展开式\optal[&=]

    \@protected@testopt \optal \\optal {=}[&=]
    

    (请注意,这\\optal是一个单一的控制序列)

  3. 的展开式\@protected@testopt

    \ifx \protect \@typeset@protect \expandafter \@testopt \else \@x@protect #1\fi
    

    也是如此#1\optal从输入流中删除)

  4. 条件为真,因此输入流中剩余的是

    \@testopt \\optal {=}[&=]
    
  5. 的展开式\@testopt

    #1#2->\kernel@ifnextchar [{#1}{#1[{#2}]}
    

    所以#1\\optal#2=(括号被去掉);输入流中剩下的是

    \kernel@ifnextchar[{\\optal}{\\optal[{=}]}[&=]
    

到目前为止,还没有发现不可扩展的标记,因此 TeX 仍在扩展标记;的扩展\kernel@ifnextchar以 开始\let,现在 TeX 确定不\omit存在。然后 TeX 继续构建对齐单元。但是,它只抓取&同一级别的下一个之前的所有内容,因此单元的内容是

\kernel@ifnextchar[{\\optal}{\\optal[{=}]}[

并且]单元格中未找到可选参数的结束符。错误消息显示

Argument of \\optal has an extra }

因为在搜索结束的]TeX 时会找到结束括号(解释它来自哪里会太长)。

有了 Sigur 的解决方案,剩下的就是

\kernel@ifnextchar[{\\optal}{\\optal[{=}]}[{&=}]

现在,&不在同一分组级别,因此单元格未终止;TeX 找到了,[所以它

\\optal[{&=}]

并且,由于扩展\\optal[#1]->a #1 b参数周围的括号被剥离,并且

a &= b

被发现,并在正确的时间终止细胞。

哇!

答案3

您可以使用所有表宏中使用的惯用语,将 隐藏&在参数扫描仪中,而不必{}在每个实例中放置一个组。但请注意(与在参数中明确使用 不同),这确实会在单元格中引入一个组,这不会影响您的示例,但原则上可能会影响(因此我修改了示例)。自动隐藏 teh而不引入mathord 原子是可能的,但更难。{\ifnum0='}{}{}+&{}

enter image description here

\documentclass[a4paper, 12pt]{book}
\usepackage{amssymb}
\usepackage{amsmath}

\begin{document}



% new command
\newcommand{\optal}{{\ifnum0=`}\fi\xoptcal}
\newcommand\xoptcal[1][=]{\ifnum0=`{\fi} +a #1 b }
%trying it out
$\optal$ \\
$\optal[ \neq ]$ \\
% trying it out inside align
\begin{align}
\optal[=]
\end{align}
%so far, so good
% trying it out with & as parameter
\begin{align}
\optal[&=]\\
+a&=b3\\
{}+a&=b3\\
\end{align}
% Fails with "Argument of \\optal has an extra } \end{align}"
% Paragraph ended before \\optal was complete \end{align}
\end{document}

相关内容