5

This forum has helped me understand how to use nested loops in TeX, but now I am having trouble using \iftoggle (from the etoolbox package) with loops. My goal is to have a toggle that can keep track of an "even" or "odd" state as the loops are progressing, where the state is updated by the code inside the loops. However, the example shown below does not work as I expect, as the toggle seems to get set to "even" every time it gets back out into the outer loop. Why does this happen, and how can I prevent it / what is a better way to achieve this functionality?

\documentclass{book}
\usepackage{etoolbox}
\begin{document}
\newcount\X
\newcount\Y

\newtoggle{even}
\toggletrue{even}

\loop
\Y = 0
\advance \X by 1
{%
  \loop
  \advance \Y by 1
  \message{\the\X,\the\Y}
  \iftoggle{even}{%
    \message{EVEN}%
    \togglefalse{even}%
  }{%
    \message{ODD}%
    \toggletrue{even}%
  }%
  \ifnum \Y < 3
  \repeat
}%
\ifnum \X < 6
\repeat
\end{document}

Output (notice the repeated EVENs):

1,1 EVEN 1,2 ODD 1,3 EVEN 2,1 EVEN 2,2 ODD 2,3 EVEN 3,1 EVEN 3,2 ODD 3,3 EVEN 4,1 EVEN 4,2 ODD 4,3 EVEN 5,1 EVEN 5,2 ODD 5,3 EVEN 6,1 EVEN 6,2 ODD 6,3 EVEN
10

This has to do with the scoping of your toggles. That is, in the inner loop, the call to \toggletrue and \togglefalse is valid, but ignored once completed, reverting back to the original definition \toggletrue{even}. That is why then output is EVEN for the start of every one of the inner loops. For these redefinitions to hold across the entire scope, prepend the toggle switches with \global:

...
\global\togglefalse{even}%
...
\global\toggletrue{even}%
...

This is the output I get when I make the above change:

1,1 EVEN 1,2 ODD 1,3 EVEN 2,1 ODD 2,2 EVEN 2,3 ODD 3,1 EVEN 3,2 ODD 3,3 EVEN 4, 1 ODD 4,2 EVEN 4,3 ODD 5,1 EVEN 5,2 ODD 5,3 EVEN 6,1 ODD 6,2 EVEN 6,3 ODD
4

You have to write \global in front of \togglefalse{even} and \toggletrue{even}.

4

If you use etoolbox, you are supposed to use \whileboolexpr. And maybe use \newcounter{X}, \value{X} instead of \newcount\X, \X. Thus:

\documentclass{minimal}
\usepackage{etoolbox}
\begin{document}
\newcounter{X}
\newcounter{Y}

\newtoggle{even}
\toggletrue{even}

\setcounter{X}{0}
\whileboolexpr{test {\ifnumcomp{\value{X}}<6} }{%
  \stepcounter{X}
  \setcounter{Y}{0}
  \whileboolexpr{test {\ifnumcomp{\value{Y}}<3} }{%
    \stepcounter{Y}
    \arabic{X}, \arabic{Y}:
    \iftoggle{even}%
      {EVEN\togglefalse{even}}%
      {ODD\toggletrue{even}}\par
  }%
}

\end{document}

I removed the extra group of inner loop, just reset \Y=0 and it will work. You'll find it looks like common for-loops in other programming languages.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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