Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'm trying to produce a command for an equation that may or may not be used inside an align element, and therefore sometimes needs a & next to the = to align the equation. I therefore defined the command \newcommand{\optal}[1][=]{a #1 b} so that when called as simply \optal it outputs the equation, but when called as \optal[&=] I can use the equation inside an align. The problem is that for some reason the command fails; it seems one cannot use & as a parameter. The problem goes away if I make the argument mandatory (ie, \newcommand{\optal}[1]{a #1 b})

Here is the MWE. I'm using Miktex 2.9 and pdflatex.

    \documentclass[a4paper, 12pt]{book}
    \usepackage{amssymb}
    \usepackage{amsmath}

    \begin{document}
    % new command
    \newcommand{\optal}[1][=]{a #1 b}
    %trying it out
    $\optal$ \\
    $\optal[ \neq ]$ \\
    % trying it out inside align
    \begin{align}
    \optal[=]
    \end{align}
    %so far, so good
    % trying it out with & as parameter
    \begin{align}
    \optal[&=]
    \end{align}
    % Fails with "Argument of \\optal has an extra } \end{align}"
    % Paragraph ended before \\optal was complete \end{align}
    \end{document}

Am I missing something? Can you think of a workaround?

share|improve this question

3 Answers 3

up vote 7 down vote accepted

Protect it with braces

\optal[{&=}]

Note that you can add more symbols to the side of an equation.

\documentclass{report}
\usepackage{amssymb}
\usepackage{amsmath}
\newcommand{\optal}[1][=]{a #1 b}

\begin{document}
$\optal$ 
$\optal[ \neq ]$ 
\begin{align}
\optal
\end{align}
\begin{align}
\optal[{&=}]         & \optal[{&=}] + \int \\
\optal[{&=}] + \iint & \optal[{&=}] - \partial
\end{align}
\end{document}

enter image description here

share|improve this answer
    
Thanks, this is a simple workaround, I've ended up using it. –  facuq Nov 13 '13 at 14:12

You've found a dark corner in the alignment process. Let's see what happens.

  1. When starting a cell in an alignment, TeX expands tokens in order to see whether \omit appears (it's used, for example, in \multicolumn for spanning columns).

  2. The expansion of \optal[&=] is

    \@protected@testopt \optal \\optal {=}[&=]
    

    (note that \\optal is a single control sequence)

  3. The expansion of \@protected@testopt is

    \ifx \protect \@typeset@protect \expandafter \@testopt \else \@x@protect #1\fi
    

    so #1 is \optal (which is removed from the input stream)

  4. The conditional is true, so what remains in the input stream is

    \@testopt \\optal {=}[&=]
    
  5. The expansion of \@testopt is

    #1#2->\kernel@ifnextchar [{#1}{#1[{#2}]}
    

    so #1 is \\optal and #2 is = (the braces are stripped off); what remains in the input stream is

    \kernel@ifnextchar[{\\optal}{\\optal[{=}]}[&=]
    

Up to now no unexpandable token has been found, so TeX is still expanding tokens; the expansion of \kernel@ifnextchar starts with \let and now TeX determines that no \omit was present. Then TeX proceeds to build the alignment cell. However, it grabs only everything *up to the next & at the same level, so the contents of the cell is

\kernel@ifnextchar[{\\optal}{\\optal[{=}]}[

and no closing ] for the optional argument is found in the cell. The error message says

Argument of \\optal has an extra }

because in the search for the closing ] TeX find a closing brace (it would be too long to explain where it comes from).

With Sigur's workaround, what remains is

\kernel@ifnextchar[{\\optal}{\\optal[{=}]}[{&=}]

and now the & is not at the same level of grouping, so the cell is not terminated; TeX finds the [ so it does

\\optal[{&=}]

and, since the expansion of \\optal is [#1]->a #1 b the braces around the argument are stripped off and

a &= b

is found, which terminates the cell at the right time.

Wow!

share|improve this answer
    
If I could I'd give you +10. I saw my solution cited on your dissertation. So do you confirm it?! lol It was right? –  Sigur Nov 11 '13 at 23:54
1  
@Sigur Yes, of course. ;-) –  egreg Nov 12 '13 at 0:19
    
Dark indeed, I found it weird that no other (sensible) argument could trigger the same error. Awesome explanation, it seems I have to learn TeX as well since it can show it's teeth occasionaly. –  facuq Nov 13 '13 at 14:16

You can hide the & from the argument scanner without having to put a {} group in every instance by using the {\ifnum0='} idiom used in all table macros. Note however that (unlike the explicit use of {} within the argument) this does introduce a {} group into the cell, which does not affect your example but could in principle (hence my modified example with +. Hiding teh & automatically without introducing a {} mathord atom is possible but harder.

enter image description here

\documentclass[a4paper, 12pt]{book}
\usepackage{amssymb}
\usepackage{amsmath}

\begin{document}



% new command
\newcommand{\optal}{{\ifnum0=`}\fi\xoptcal}
\newcommand\xoptcal[1][=]{\ifnum0=`{\fi} +a #1 b }
%trying it out
$\optal$ \\
$\optal[ \neq ]$ \\
% trying it out inside align
\begin{align}
\optal[=]
\end{align}
%so far, so good
% trying it out with & as parameter
\begin{align}
\optal[&=]\\
+a&=b3\\
{}+a&=b3\\
\end{align}
% Fails with "Argument of \\optal has an extra } \end{align}"
% Paragraph ended before \\optal was complete \end{align}
\end{document}
share|improve this answer
    
Thanks, this is indeed exactly what I had in mind when using the command, but given that I define such commands so often, and it's definition is so hackish, it would make them a bit messy to go through later. –  facuq Nov 13 '13 at 14:11

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.