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.

Now I want to automatically switch cols and rows by counting. I have already pinned the issue down to the alignment character &:

\newcounter{myRow}
\newcounter{myCol}[myRow]
\setcounter{myRow}{1}
\setcounter{myCol}{1}

\newcommand{\testcell}{%
  \fbox{\themyRow, \themyCol}%
  \ifnum\value{myCol}<3%
    &%
  \else%
    \refstepcounter{myRow}%
    \tabularnewline%
  \fi%
  \refstepcounter{myCol}%
}

\newcommand{\testcelltwo}{%
  \fbox{\themyRow, \themyCol}%
  \ifnum\value{myCol}<3%
%     &% (This is the only difference to \testcell)
  \else%
    \refstepcounter{myRow}%
    \tabularnewline%
  \fi%
  \refstepcounter{myCol}%
}

\begin{document}%
  % This raises "incomplete ifnum" errors and looks broken
  \begin{tabular}{lll}
    \testcell \testcell \testcell \testcell \testcell \testcell
  \end{tabular} \par
  % This works fine
  \begin{tabular}{lll}
    \testcelltwo & \testcelltwo & \testcelltwo \testcelltwo & \testcelltwo & \testcelltwo
  \end{tabular}
\end{document}

How to fix that? The usual sources only try to teach me how to use the tabular environment correctly.

share|improve this question

1 Answer 1

up vote 7 down vote accepted

You have to issue & or \tabularnewline when the conditional has already ended; the usual trick is to use \@firstoftwo and \@secondoftwo.

\documentclass{article}
\newcounter{myRow}
\newcounter{myCol}[myRow]
\setcounter{myRow}{1}
\setcounter{myCol}{1}

\makeatletter
\newcommand{\testcell}{%
  \fbox{\themyRow, \themyCol}%
  \ifnum\value{myCol}<3
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {&\refstepcounter{myCol}}%
  {\refstepcounter{myRow}\tabularnewline\refstepcounter{myCol}}%
}
\makeatother

\begin{document}
\begin{tabular}{lll}
\testcell \testcell \testcell \testcell \testcell \testcell
\end{tabular}
\end{document}

enter image description here

Note: one of the % in the definition of \testcell is redundant. Exercise: which one?


Some notes about the trick. If the conditional is true, then \ifnum and the tokens necessary for the comparison are removed, leaving

\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{&\refstepcounter{myCol}}{\refstepcounter{myRow}\tabularnewline\refstepcounter{myCol}}

in the input stream. Now \expandafter expands \else, whose expansion is empty after gobbling everything up to and including the matching \fi, leaving

\@firstoftwo{&\refstepcounter{myCol}}{\refstepcounter{myRow}\tabularnewline\refstepcounter{myCol}}

which then becomes

&\refstepcounter{myCol}

In case the conditional is false, the tokens for the comparison are removed, but together with everything up to and including \else, so in the input stream we have

\expandafter\@secondoftwo\fi
{&\refstepcounter{myCol}}{\refstepcounter{myRow}\tabularnewline\refstepcounter{myCol}}

Now \expandafter expands \fi, whose expansion is empty, leaving

\@secondoftwo{&\refstepcounter{myCol}}{\refstepcounter{myRow}\tabularnewline\refstepcounter{myCol}}

and then

\refstepcounter{myRow}\tabularnewline\refstepcounter{myCol}

as desired.

To be honest, there are other redundant % in the definition, but only because we are in a tabular, so this is not general enough for omitting them. The redundant one is the % between the two braced groups following \fi, because TeX discards spaces when looking for undelimited arguments.

share|improve this answer
    
I never saw \@firstoftwo nor \@secondoftwo before. To be sure to have gotten it right: expandafter defers expansion of these to when the token after them was fully expanded. The token after them is not \fi nor \else but the groups either with & resp. tabularnewline inside. So first the conditional is expanded to either \expandafter\@firstoftwo or \expandafter\@secondoftwo, then the groups are attached and the \@... macro finally chooses the group to put. This renders the % between the groups redundant as it is never chosen over them. –  LDericher Jun 22 at 21:39
    
@LDericher Not really. The trick has been explained elsewhere, but I'll add some words about it. –  egreg Jun 22 at 21:48
    
I still try to read TeX like an imperative paradigm, where an "input stream of instructions" is rather uncommon. Your explanation is as beautiful as your solution and roughly matches what I intended to say in my previous comment, though I didn't know yet how exactly TeX expands a conditional yet. Is this what do you do for a living? Or did you just at some point devour The Art of Computer Programming? –  LDericher Jun 22 at 22:10
    
@LDericher The TeXbook, in particular; but also TeX by Topic, The LaTeX companion, several numbers of TUGboat. And of course my own book on LaTeX programming. ;-) –  egreg Jun 22 at 22:12
    
Although it's not totally redundant: Since it's inside a definition it saves one character token's worth of memory, and @egreg is old enough to recall a time when that was important. –  David Carlisle Jun 23 at 8:29

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.