1

I have the following code

\begin{document}
\newcommand{\spec}[2][]{\sigma_{#1}\left(#2\right)}

\newcounter{i}%
\newtoks\striche%
\newcommand{\commu}[2][1]{%
    \setcounter{i}{1}%
    \striche={'}%
    \loop%
    \ifnum\value{i}<#1%
        \striche=\expandafter{\the\expandafter\striche'}%
        \stepcounter{i}%
    \repeat%
    {#2}\the\striche%
}

$\spec[\commu[2]{C}]{x}$
\end{document}

I get the error message argument of \\commu has an extra }. Both macros separately are working fine. I figured out that

\spec[\commu{C}]{x}

does work. So the problem seems to be the optional parameter of \commu. Is there any way stack two macros with optional parameters? Or what am I doing wrong?

3
  • What is the benefit of using \commu[2]{C} rather than C''?
    – Manuel
    Commented Oct 31, 2017 at 9:58
  • That I can change my notation later, if I find a better one. Commented Oct 31, 2017 at 10:00
  • Yes, of course. But you can make an intelligent macro too, that lets you write C'' which is shorter than \commu[2]{C}. It was just to note that may be you did not need the macro ;)
    – Manuel
    Commented Oct 31, 2017 at 10:03

2 Answers 2

3

The problem is that you are using [] inside []. To hide this from tex, you can wrap your macro in an additional set of {}:

\documentclass{article}

\begin{document}
\newcommand{\spec}[2][]{\sigma_{#1}\left(#2\right)}

\newcounter{i}%
\newtoks\striche%
\newcommand{\commu}[2][1]{%
    \setcounter{i}{1}%
    \striche={'}%
    \loop%
    \ifnum\value{i}<#1%
        \striche=\expandafter{\the\expandafter\striche'}%
        \stepcounter{i}%
    \repeat%
    {#2}\the\striche%
}

$\spec[{\commu[2]{C}}]{x}$
\end{document}

enter image description here

2
  • 1
    Or use xparse \NewDocumentCommand\spec{om}{\sigma\IfValueT{#1}{_{#1}}\left(#2\right)} and then \spec[\commu[2]{c}]{x} and also define \commu this way to be sure (with O{1} rather than o in the argument definition).
    – Manuel
    Commented Oct 30, 2017 at 12:28
  • @Manuel I guess showing how to do this with xparse would be an interesting answer on its own. I would certainly upvote, if you would write one! Commented Oct 30, 2017 at 12:40
2

Typing \spec[{\commu[2]{C}}]{x} would solve the problem, but I think you can enjoy a different solution with xparse, which allows to take care of some other small issues.

I've made two adjustments: first remove \left and \right whose only effect is to add unwanted horizontal space before and after the parentheses; second, add the subscript only if present.

There is a difference between no subscript and an empty one; in the latter case TeX adds a horizontal space of size \scriptspace (default value is 0.5pt); in the example I make it very large to show what happens. The length 0.5pt is small, but noticeable when present.

The syntax for the definition of \spec is that it has an optional argument o and a mandatory one. If the optional argument is present in the later input, the condition \IfValueT is true and the relative tokens are used (it's a shorthand for \IfValueTF{_{#1}}{}, here in the false case we do nothing).

In the definition of \commu, the optional argument receives a default value of 1, so it's denoted as O{1}.

With expl3 (on which xparse is based) the loop can be greatly simplified.

\documentclass{article}
\usepackage{xparse}

\NewDocumentCommand{\spec}{om}{%
  \sigma
  \IfValueT{#1}{_{#1}}%
  (#2)%
}

\ExplSyntaxOn % we need to access lower level functions; here spaces are ignored

\NewDocumentCommand{\commu}{O{1}m}
 {
  #2\prg_replicate:nn { #1 } { ' }
 }

\ExplSyntaxOff

\begin{document}

$\spec[\commu[2]{C}]{x}$ % no braces required

\bigskip

% let's show why \IfValueT is necessary
\setlength{\scriptspace}{20pt}

$\spec{x}$

$\sigma_{}(x)$ % what you'd get without the trick

\end{document}

Note that no additional braces are necessary here.

enter image description here

2
  • why is the optional keyword in the case where no default value is set a smallo and in the other case a big O. Moreover why do the default case needs the m in brackets? Commented Oct 30, 2017 at 15:53
  • @NathanaelSkrepek The {m} was a typo. The difference between o and O{...} is that in the first case you can test the presence of the optional argument with \IfValueTF; in the second case, the absence of the optional argument means ... is used.
    – egreg
    Commented Oct 30, 2017 at 16:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .