Why do I have to put braces around my macro for subscripts / indices?
Well they are missing. Not to worry, though, you can easily add them since you don't need the literal brace characters used for delimiting macro/command arguments, but can use \bgroup
and \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
At some future time, or with some unknown package, the subscript and superscript signal characters (_
and ^
) could conceivably be implemented as "active" character commands that take arguments, in which case explicit brace grouping would be required.
Subscripts (and superscripts—what I say here is valid for both) in TeX only work without braces for single tokens (or some special low-level cases like \char<number>
; not really LaTeX syntax), so you can write 2^n
rather than the comparatively long 2^{n}
. If next unexpandable token (except \relax
) after a superscript character is a {
(or other begin-group character token), then TeX takes a balanced list of tokens for the superscript. TeX also expands tokens after a superscript, so you can define shorthands like \def\funny#1{{#1+n}}
then write 2^\funny{1}
(\funny{1}
expands to {1+n}
and the braces are there).
However some commands don't expand properly to a neatly braced list of tokens like \funny
or \mathrm
do: they are designed to work in subscripts without surrounding braces by expanding to a braced list of tokens. In your command, the first unexpandable token is a \let
(in the definition of \@ifnextchar
, in the definition of \@ifstar
) so when TeX sees it, it knows that a \let
alone doesn't work and tells you that you forgot a {
at that point:
! Missing { inserted.
<to be read again>
\let
l.16 $\sigma_\ind
{xy}$ % does not work
?
If you are bold, you can ignore this error and the next one. TeX will try to recover and in this one particular situation it will add the two missing braces, making both lines essentially the same.
Use braces: that's the proper syntax!
That said :-)
With xparse
you can define a version of that command that looks for optional arguments expandably, then adds the missing braces in the definition:
\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}