# Problem setting a flag inside a TikZ \foreach loop

I'm pulling my hair out trying to understand why the following doesn't work. The intention is to calculate whether a given number #1 is prime, and to set \isprime to either 1 (true) or 0 (false). The looping and the conditionals are doing the right thing, but the \isprime flag isn't being set properly.

 \newcommand{\setisprime}[1]{
\def\isprime{1}
\foreach \i in {2, 3,5,...,#1} {
\pgfmathparse{\i*\i>#1? 1:0}
\ifthenelse{\pgfmathresult=1}{
% Early-out if \i^2 > #1
\breakforeach
}{
% Otherwise test if \i divides #1
\pgfmathparse{Mod(#1,\i)==0? 1:0}
\ifthenelse{\pgfmathresult=1}{
\def\isprime{0}
\breakforeach
}{}
}
}
}


Here's what happens:

Here's an MWE with debugging statements:

 \documentclass{article}
\pagestyle{empty}

\usepackage{tikz}
\usepackage{ifthen}

\begin{document}

\newcommand{\debugsetisprime}[1]{
Testing #1 for primeness.\par
\def\isprime{1}
\foreach \i in {2, 3,5,...,#1} {
\pgfmathparse{\i*\i>#1? 1:0}
\ifthenelse{\pgfmathresult=1}{
Exiting loop because $\i^2 > #1$.\par
\breakforeach
}{
Testing whether \i\ divides #1...
\pgfmathparse{Mod(#1,\i)==0? 1:0}
\ifthenelse{\pgfmathresult=1}{
Yes.\par Exiting loop because divisor found.\par
\def\isprime{0}
\breakforeach
}{
No.\par
}
}
}
\ifnum\isprime=1
#1 is prime.\par\vskip1em
\else
#1 is not prime.\par\vskip1em
\fi
}

\debugsetisprime{97}
\debugsetisprime{15}

\end{document}

-
\foreach loops are computed in a group; use \gdef instead of \def –  egreg Feb 17 '12 at 23:58

The problem here is that the redefinition of \isprime to 0 in

\def\isprime{0}


is made inside a group. As such, it is local and doesn't "survive" outside the group. Use

\global\def\isprime{0}


instead (or \gdef for short). There is no need for this \global definition when initializing \isprime, since it is at the same depth as the eventual test for primeness.

-
Sweet!!! Huh, all this time I never knew that defintions in TeX weren't all global. This is great news! –  Todd Lehman Feb 17 '12 at 23:59