# Booleans fail in tabular environment

I've got a workaround for this problem, but maybe someone knows a cleaner way to fix it. I'm using the standard packages in TexLive 2009.

Here's the code that doesn't work:

\documentclass{article}
\usepackage{ifthen}
\newboolean{test}
\setboolean{test}{false}
\newcommand{\testval}{\ifthenelse{\boolean{test}}{yes}{no}}
\begin{document}
\begin{tabular}{ll}
Should be no & \testval \\
Change value & \setboolean{test}{true} \\
Shoule be yes & \testval \\
\end{tabular}
\end{document}


I haven't seen any mention of this behavior in the ifthen package description. I've also noticed that, for instance, you can't use \newcommand and \isundefined to work around this.

My workaround so far is to use a counter, and then test \value{counter}=0. The only difficulty was that there's no \providecounter the way there is with booleans or commands, so I wrote providecounter.sty:

\NeedsTeXFormat{LaTeX2e}[1994/12/01]
\ProvidesPackage{providecounter}
[2010/11/16 my hack to implement a providecounter command]

\def\providecounter#1{\@ifundefined{c@#1}{\newcounter{#1}}\relax}


So, two questions: a. why do \setboolean and \newcommand not work inside a tabular environment, and b. do counters more or less not care where they are defined?

-
Your code doesn't work because of a missing backslash (it should be \newcommand{\testval}), and if the backslash is added, your code works for me (it yields "no" in the first and "yes" in the second table row). –  lockstep Nov 16 '10 at 20:33
Yeah, that was a typo; also, oddly enough setboolean will work if it's on the same row. I checked this one. ;-) –  Ben Nov 16 '10 at 20:37

It seems that resetting the boolean is only effective local (i.e. within the same table cell). Using the \global prefix yields an error message. While I don't have a full explanation, I have a (workaround?) solution: Use the etoolbox package and its commands instead of ifthen - and only then use the \global prefix.

\documentclass{article}
\usepackage{etoolbox}
\newbool{test}
\setbool{test}{false}
\newcommand{\testval}{\ifbool{test}{yes}{no}}
\begin{document}
\begin{tabular}{ll}
Should be no & \testval \\
Change value & \global\setbool{test}{true} \\
Should be yes & \testval \\
\end{tabular}
\end{document}


EDIT: I think I understand. Resetting a boolean obviously obeys the normal LaTeX scope rules - i.e., if it is done within a group, its effect will be limited to that group. On the other hand , "[t]he commands to change counter values are global declarations" (Leslie Lamport - LaTeX. A document preparation system, p. 98) - that's why your workaround with counters succeeded.

-
I remember running into this behavior once. Took me forever to figure it out. –  Matthew Leingang Nov 16 '10 at 21:18
The fact that cells in a table are local goes all the way back to TeX's \halign. Knuth says in the TeXbook (buried in an aside) that each entry is treated as though it is wrapped in braces. So you have to use \global to escape the box. –  Ryan Reich Nov 16 '10 at 23:12
With ifthen you can set the boolean globally with \global\testtrue. –  Ulrike Fischer Nov 17 '10 at 18:03