# Why do I have to put braces around my macro for subscripts / indices?

I want to define a macro \ind which let's me set in math mode a subscript in upright letters and when starred (\ind*) in italic letters. Additionally, an optional argument allows me to adjust the kerning between letter and index, i.e. W_{\ind[-2mu]{x}}. This works quite well. But surprisingly, I have to put braces around the \ind-command in order to make it run.

Can someone explain me why I have to put braces around the command and how I can modify the macro to avoid this? It's a super big deal but I would like to understand the mechanism behind it.

The error is always that a { and a } is missing.

MWE:

\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}

• Welcome to TeX.SX! Commands that do work without braces, like \text are really an exception to the rule. The proper LaTeX syntax requires braces: if something works without them it's by accident. What makes it not work in your case is the \@ifstar test. Aug 1 '20 at 0:07
• IIRC things like \def\ind#1{ { do something with #1 } } works. So perhaps \newcommand\ind[1]{ { \@ifstar \ind@star \ind@nostar #1 } } works. Aug 1 '20 at 0:20
• @Symbol1 It would only if none of the optional arguments were given. Otherwise the argument #1 would be a * or a [ and the command wouldn't work properly. Aug 1 '20 at 1:02
• Ooooof yeah you are right. Let's me not having enough sleep. Aug 1 '20 at 2:13
• @PhelypeOleinik Do you mean \sigma_\text{xy} works? That's really unexpected. How come? Aug 1 '20 at 16:18

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.

• I tried \bgroup and \egroup but apparently not at the correct positions. Thanks! Aug 1 '20 at 10:01

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.
\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}


• It's not actually single tokens or explicitly braced material for superscripts and subscripts -- that's the rule for macro arguments. A sub/superscript is a <math field> which consists of filler followed by one of: a character (including \char commands), or a math character (includes \matchar and \delimiter commands), or math mode material in braces (either {} or \bgroup\egroup) . So $z_ \relax \mathchar121$ gives an upright y subscript. Aug 1 '20 at 9:23
• Your answer is very useful. In both ways understanding and circumventing the problem. But I like Donald's solution a bit more since it works without an additional package. Aug 1 '20 at 10:04
• I also like the demonstration of an expandable command with optional arguments in which one can use explicit braces! Aug 1 '20 at 10:17
• @DonaldArseneau It seems I oversimplified a bit. Thanks for pointing it out! :-) Aug 1 '20 at 14:44
• @MarcKrass No problem; glad you liked. Just for the record, starting with the 2020-10-01 release of LaTeX, xparse will be loaded in the LaTeX kernel (If you have TeXLive 2020 or MiKTeX you can already test that by using pdflatex-dev; see latex-project.org/news/2020/07/22/latex-dev-2020-10-1b) Aug 1 '20 at 14:47