我想定义一个宏\ind
,让我在数学模式下设置直立字母的下标,当标有星号 ( \ind*
) 时则设置斜体字母的下标。此外,一个可选参数允许我调整字母和索引之间的字距,即W_{\ind[-2mu]{x}}
。这很有效。但令人惊讶的是,我必须在\ind
-command 周围加上括号才能使其运行。
有人能解释一下为什么我必须在命令两边加上括号,以及如何修改宏来避免这种情况吗?这是一件大事,但我想了解其背后的机制。
错误总是缺少a{
和 a 。}
梅威瑟:
\documentclass{article}
\makeatletter
\newcommand\ind{\@ifstar{\ind@star}{\ind@nostar}}
\newcommand\ind@star[2][]{\mkern \muexpr 0mu #1 #2}
\newcommand\ind@nostar[2][]{\mathrm{\mkern \muexpr 0mu #1 #2}}
\makeatother
\begin{document}
$\sigma_{\ind{xy}}$ % works
$\sigma_\ind{xy}$ % does not work
\end{document}
答案1
嗯,它们不见了。不过不用担心,您可以轻松添加它们,因为您不需要用于分隔宏/命令参数的文字括号字符,但可以使用\bgroup
和\egroup
。
\makeatletter
\newcommand\ind{\bgroup\@ifstar{\ind@star}{\ind@nostar}}
\newcommand\ind@star[2][]{\mkern \muexpr 0mu #1 #2\egroup}
\newcommand\ind@nostar[2][]{\mathrm{\mkern \muexpr 0mu #1 #2}\egroup}
\makeatother
在未来的某个时间,或者使用某些未知的包,下标和上标信号字符(_
和^
)可以实现为接受参数的“活动”字符命令,在这种情况下需要显式括号分组。
答案2
TeX 中的下标(和上标——我在这里说的对两者都有效)只适用于单个标记(或一些特殊的低级情况,如\char<number>
;不是真正的 LaTeX 语法),因此你可以写2^n
而不是相对较长的2^{n}
。如果接下来不可扩张\relax
上标字符后的标记(除了)是 a {
(或其他起始组字符标记),则 TeX 会为上标取一个平衡的标记列表。TeX 还会扩展上标后的标记,因此您可以定义简写,例如,\def\funny#1{{#1+n}}
然后写入2^\funny{1}
(\funny{1}
扩展为{1+n}
,括号在那里)。
但是有些命令无法正确扩展为整齐的括号标记列表,例如\funny
或\mathrm
:它们被设计为通过扩展为括号标记列表来在下标中工作而无需括号。在您的命令中,第一个不可扩展的标记是 a \let
(在 的定义中\@ifnextchar
,在 的定义中\@ifstar
),因此当 TeX 看到它时,它知道\let
单独的 a 不起作用并告诉您您{
当时忘记了 a :
! Missing { inserted.
<to be read again>
\let
l.16 $\sigma_\ind
{xy}$ % does not work
?
如果你够大胆,你可以忽略这个错误和下一个错误。TeX 会尝试恢复,在这个特殊情况下,它会添加两个缺失的括号,使两行本质上相同。
使用括号:这是正确的语法!
话虽如此:-)
您xparse
可以定义该命令的一个版本,该版本可扩展地查找可选参数,然后在定义中添加缺少的括号:
\documentclass{article}
\usepackage{xparse}
\makeatletter
\NewExpandableDocumentCommand \ind { s O{} m}
{{% <- extra set of braces
\IfBooleanF{#1}{\mathrm}% If no star argument
{\mkern \muexpr 0mu #2 #3}%
}}
\makeatother
\begin{document}
$\sigma_{\ind{xy}}$ % works
$\sigma_\ind{xy}$ % works
$\sigma_\ind[-5mu]{xy}$ % also works
\end{document}