17

In other words, is bool{testB} evaluated at all in this example code?

\newbool{testA}
\newbool{testB}
\booltrue{testA}
\booltrue{testB}
\ifboolexpr{ bool{testA} or bool{testB} }{OK}{Something's wrong...}

(I am too lazy (pun intended;)) to check in the source, the documentation seems to say nothing about it – maybe someone just knows that and doesn't have to analyze the source (which I did look into, but didn't understand it at a first glance)? If it isn't something obvious, I'll be happy to do my homework, dig into the source and try to establish this.)

mbork
  • 13,385

2 Answers2

15

The evaluation is not lazy, revealed by scanning the .log when tracing the macro expansions:

%\begingroup
\tracingmacros1
\ifboolexpr{ bool{testA} or bool{testB} }{OK}{Something's wrong...}
%\endgroup

That is, a complete evaluation of bool{testA} is followed by an equivalent evaluation of bool{testB}, followed by an evaluation of or, to output \@firstoftwo{OK}{Something's wrong...}.

Depending on your inspection of the macro expansion, you may require the use of a group to limit the output to the .log.

Werner
  • 603,163
  • 4
    I'd have gone for a faster route: \ifboolexpr{ bool{testA} or bool{\ERROR} } would work with testA true and lazy evaluation, but fails so evaluation can't be lazy :-) – Joseph Wright Apr 02 '14 at 07:21
  • 7
    @JosephWright: I see, the lazy approach to detecting whether the evaluation is lazy. :) – Werner Apr 02 '14 at 07:23
7

The answer has been given by Werner. xintexpr knows about etoolbox booleans and toggles. Different syntaxes allow different levels of laziness:

[sorry I got wrong the way "lazy" was to be interpreted; thus I switch to "silly"]

  1. silly: booleans are replaced by 1 or 0 depending on whether they evaluate to true or false, and then the logical or does not stop scanning these 1's or 0's even if it has found already a true one.
  2. semi-silly: the booleans are evaluated but the or stops when it has found a true one
  3. not silly: booleans are not evaluated unless really needed.

In the code snippet below, the three different syntaxes realize the three possibilities described above:

\documentclass{article}
\usepackage{etoolbox}
\usepackage{xintexpr}

\begin{document}
\newbool{testA}
\newbool{testB}
\newbool{testC}
\booltrue{testA}
\booltrue{testB}
\booltrue{testC}

%\tracingmacros1

% silly
\xintifboolexpr{ bool(testA) | bool(testB) | bool(testC) }{OK}{Something's wrong...}

% semi-silly
\xintifboolexpr{ any(bool(testA),bool(testB),bool(testC)) }{OK}{Something's wrong...}

% not silly
\xintifboolexpr{ bool(testA)?1{bool(testB)?1{bool(testC)}} }{OK}{Something's wrong...}

\end{document}
  • 3
    I rolled-back twice my edits... :-( I realized I had interpreted "lazy" as the opposite of its signification in the OP, then I changed my mind, then I again changed my mind. (this is all because "lazy" has a pejorative connotation, while in fact it is the intelligent thing to do; perhaps even generally ;-)) –  Apr 02 '14 at 08:36
  • With release 1.1 of xint ([2014/10/28]), the || for OR and && for AND are preferred to single | and &. One can also use 'or', 'and', 'xor' (straight quotes mandatory). –  Nov 29 '14 at 17:01