20

I’m struggling with getting \ifmmode to work correctly when used inside an array environment which is inside a displaymath environment.

Here is a minimal example:

\documentclass{article}

\newcommand{\signal}[1]{%
  \ifmmode
    1#1
  \else
    2$#1$
  \fi
}

\begin{document}
\begin{displaymath}
  \begin{array}{cc}
    \signal{a} \signal{b} & \signal{c} \signal{d} \\
  \end{array}
\end{displaymath}
\end{document}

This example generates the following output:

2a 1 _b_ 2c 1 _d_

Why doesn’t all invokations of \signal detect math-mode?

David Carlisle
  • 757,742
gablin
  • 17,006

1 Answers1

24

At the start of an alignment cell, TeX is looking for an \omit or \noalign, rather than being in math mode. The way to deal with this is to insert a \relax.

\documentclass{article}

\newcommand{\signal}[1]{%
  \relax
  \ifmmode
    1#1
  \else
    2$#1$
  \fi
}

\begin{document}
\begin{displaymath}
  \begin{array}{cc}
    \signal{a} \signal{b} & \signal{c} \signal{d} \\
  \end{array}
\end{displaymath}
\end{document}

Now, the issue with that is that it will mess up kerning if used in other places (it puts a \relax in even when it's not needed). In some LaTeX3 work, we've experimented with an approach to 'pick up' the alignment cell using e-TeX. At one point we had something very elaborate to test for this

\documentclass{article}

\newcommand{\signal}[1]{%
  \ifnum\currentgrouptype = 6 %
    \ifnum\lastnodetype = 0 %
    \else
      \ifnum\lastnodetype = 7 %
      \else
        \relax
      \fi
    \fi
  \fi
  \ifmmode
    1#1
  \else
    2$#1$
  \fi
}

\begin{document}
\begin{displaymath}
  \begin{array}{cc}
    \signal{a} \signal{b} & \signal{c} \signal{d} \\
  \end{array}
\end{displaymath}
\end{document}

This uses the various diagnostics from e-TeX to pick up the start of a cell. However, this is really not a good idea as it pretends to be expandable but does insert \relax: not expandable! A much cleaner approach is to use \protected

\documentclass{article}

\protected\def\signal#1{%
  \ifmmode
    1#1
  \else
    2$#1$
  \fi
}

\begin{document}
\begin{displaymath}
  \begin{array}{cc}
    \signal{a} \signal{b} & \signal{c} \signal{d} \\
  \end{array}
\end{displaymath}
\end{document}

as e-TeX does not expand protected macros here.

David Carlisle
  • 757,742
Joseph Wright
  • 259,911
  • 34
  • 706
  • 1,036
  • 1
    Joseph, we're not in math mode: that will be started when TeX inserts the u part for the cell (in the terminology of the TeXbook) and ended with the v part. Saying \omit won't give math mode, for example; LaTeX takes precautions to add again the $ characters when \multicolumn is used in an array. But this is almost splitting hairs, I guess. :) – egreg Sep 05 '11 at 21:41