2

I'd like to define a command which expands to { <output> } instead of <output>. I've tried wrapping the command contents with additional

  • { / }
  • \bgroup / \egroup
  • \begingroup / \endgroup
  • \group_begin: / \group_end:
  • \c_group_begin_token / \c_group_end_token
  • \str_use:N \c_left_brace_str / \str_use:N \c_right_brace_str

but to no avail.

My use case: I'd like to be able to write \R[1][2] instead of \mathbb{R}^{1 \times 2}, but also be able to use this in subscripts and superscripts, like 0_\R[1][2], without needing to surround it with braces. I know, this is rather specific and maybe lazy, but I'm honestly also just curious about this from a TeXnical point of view.

Simplified MWE:

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn

\DeclareDocumentCommand { \R } { o } { \mathbf { R } \IfValueT { #1 } { \sp { #1 } } }

\DeclareDocumentCommand { \Q } { m } { \mathbf { Q } \sp { #1 } }

\ExplSyntaxOff

\begin{document}

$0_\R$ % throws error "Missing } inserted" $0_\R[2]$ % throws error "Missing } inserted" $0_\Q{2}$ % expands to $0_\mathbf{Q}^{2}$, not $0_{\mathbf{Q}^{2}}$

\end{document}

steve
  • 2,154
  • 2
    using braces for super and subscripts is a feature it's really unfortunate that some horrors like x_\text{aaa} sort of half work and don't give an error – David Carlisle Jan 26 '24 at 17:57
  • You can not have a trailing optional argument via an expandable command and to make you o_\R... work \R needs to expand to a brace group, so it's quite hard to do what you want but would be trivial but bad practice if \R had a mandatory {} argument rather than [] – David Carlisle Jan 26 '24 at 18:04
  • sorry I only fixed \R in my original answer just spotted you wanted \Q as well, updated. – David Carlisle Jan 26 '24 at 19:31
  • @DavidCarlisle When you say that x_\text{aaa} sort of "half" works, are you just referring to the fact that it's not good practice (https://tex.stackexchange.com/a/82338/170958), or is there actually any "functional" difference between x_\text{aaa} and x_{\text{aaa}}, specifically? My understanding was that those code snippets would be equivalent to x\sb\text{aaa} and x\sb{\text{aaa}}, respectively, and that those two are essentially equivalent to one another (https://tex.stackexchange.com/a/1929/170958). – steve Jan 27 '24 at 01:04
  • the parsing is completely specific to sub and super, you can't do \fbox\text{aaa} it has to be \fbox{\text{aaa}} so if anything tries to redefine ^ as an active macro with a normal #1 style argument, it'll fail. and it's a bad habit to get in to, if you have \def\foo{abc} and do \fbox\foo that is \fbox{abc} but x^\foo is x^{a}bc as ^ expands tokens looking for { (which is why the answers work) but is almost never what you want and x^{abc} was intended but you get the wrong thing with no warning – David Carlisle Jan 27 '24 at 02:29

2 Answers2

3

I'd avoid being lazy about braces. Laziness is good in other places.

For instance, you should define some \numberset command in order to achieve uniformity in how the symbols are typeset (and you can later decide to change all of them in one sweep).

You shouldn't be using \DeclareDocumentCommand, anyway: you risk to redefine without warning an important command.

Now the abstraction:

\documentclass{article}

\NewDocumentCommand{\numberset}{m}{\mathbf{#1}} \NewDocumentCommand{\vecspace}{m}{\bgroup\VECSPACE{#1}} \NewDocumentCommand{\VECSPACE}{moo}{% #1% \IfValueT{#2}{^{#2\IfValueT{#3}{\times #3}}}% \egroup }

\NewDocumentCommand{\R}{}{\vecspace{\numberset{R}}} \NewDocumentCommand{\Q}{}{\vecspace{\numberset{Q}}}

\begin{document}

$0_\R$ $0_\R[2]$ $0_\R[2][3]$

$0_\Q$ $0_\Q[2]$ $0_\Q[2][3]$

$0_\vecspace{V}[1][2]$

$0_\vecspace{\numberset{J}}[1][2]$

\end{document}

This way you can accommodate occasional different situations.

However, I insist that

0_{\R[2]}

is much better and doesn't cost too much. For this you just remove one layer:

\NewDocumentCommand{\vecspace}{moo}{%
  #1%
  \IfValueT{#2}{^{#2\IfValueT{#3}{\times #3}}}%
}

enter image description here

egreg
  • 1,121,712
  • Thank you for your answer and the recommendations regarding best practices, I really appreciate it. I've gotten used to notational shortcuts, which I do believe can be very useful and have their place, but it's good to know where to draw the line, so to speak. – steve Jan 27 '24 at 00:54
2

You need the command to expand to a brace group, but super and subscripts should always be braced.

\documentclass{article}

% only needed in old latex releases \usepackage{xparse}

\ExplSyntaxOn

% Please don't do this \DeclareDocumentCommand\R{}{\bgroup\Rinner}

\DeclareDocumentCommand { \Rinner } { o } { \mathbf { R } \IfValueT { #1 } { \sp { #1 }} \egroup }

\DeclareDocumentCommand { \Q } { m } { {\mathbf { Q } \sp { #1 }} }

\ExplSyntaxOff

\begin{document}

$0_\R$ % throws error "Missing } inserted" $0_\R[2]$ % throws error "Missing } inserted" $0_\Q{2}$ % expands to $0_\mathbf{Q}^{2}$, not $0_{\mathbf{Q}^{2}}$

\end{document}

enter image description here

David Carlisle
  • 757,742
  • I see — I had just gotten used to shortcuts like a_\text{b}, but I appreciate that they're not best practice, and will stick with manually adding braces. But I really appreciate your answer, it makes sense. Does that mean that \NewDocumentCommand{\test}{}{...} and \NewDocumentCommand{\test}{}{{...}} (or \NewDocumentCommand{\test}{}{\bgroup...\egroup}) will always have identical behavior, because the additional braces are gobbled / ignored (if they are matched up at least, unlike with \bgroup\Rinner)? – steve Jan 27 '24 at 00:48