我正在尝试为一个方程生成一个命令,该命令可能在元素内部使用,也可能不在元素内部使用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}
答案2
您发现了对齐过程中的一个黑暗角落。让我们看看会发生什么。
当在对齐中启动一个单元格时,TeX 会扩展标记以查看是否
\omit
出现(例如,它用于\multicolumn
跨越列)。的展开式
\optal[&=]
为\@protected@testopt \optal \\optal {=}[&=]
(请注意,这
\\optal
是一个单一的控制序列)的展开式
\@protected@testopt
为\ifx \protect \@typeset@protect \expandafter \@testopt \else \@x@protect #1\fi
也是如此
#1
(\optal
从输入流中删除)条件为真,因此输入流中剩余的是
\@testopt \\optal {=}[&=]
的展开式
\@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='}
{}
{}
+
&
{}
\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}