I have a list of boolean functions {f1, f2, f3, ...}
that take a value and return True
or
False
. They are used to check whether the value meets certain conditions.
I need to run construct a nested If
statement that for an arbitrary value sequentially evaluates the boolean functions above and returns True
if all functions return True
, and False
otherwise :
If[f1[#],
If[f2[#],
If[f3[#],
True,
False],
False],
False]
It is important that this evaluation is sequetial, so that f1
is evaluated before f2
, f2
before f3
etc.; and that as soon as any of the functions returns False
, the entire evaluation stops. This is necessary because each evaluation is time-consuming, and I don't want to evaluate any other functions once one of them returns False
.
I wrote the following function to generate the nested if statement:
NestedIf[conds_] := Function[d, Fold[If[#2[d], #1, False] &, True, Reverse@conds]];
And use it within Select
statement to pick out the values from my dataset that meet all of the conditions f1
,f2
,f3
, etc.:
Select[data, NestedIf[{f1, f2, f3}]]
However, the problem with this function is that once I pass it a value, it first evaluates all conditions and only then inserts them into the nested If
structure. So I get no time savings.
I tried using SetAttributes[NestedIf,HoldAll]
, but that did not help because the arguments are still evaluated first.
How can I prevent the arguments from being evaluated prematurely?
P.S. AllTrue
command does something very similar to what I want, by sequentially checking if all values in a list satisfies one test. What I need is to test whether one value satisfies a list of tests.
P.P.S. Several people have suggested using And
for sequential evaluation. Unfortunately the problem is that all the arguments ends up being evaluated before And
begins sequential evaluation. For example, try running this:
f1[x_] := (Print["First"]; x > 10);
f2[x_] := (Print["Second"]; x > 20);
And[Through[{f1, f2}[#]]] & @ 5
The output will be:
First
Second
{False, False}
So both arguments are evaluated before they are passed to And
, and I'm trying to find a way to prevent that.
Which[]
andAllTrue[]
andAnd[]
. $\endgroup$And
will evaluate its arguments sequentially, returningFalse
as soon as any argument isFalse
. $\endgroup$And
itself doesn't evaluate arguments sequentially, but that by the time it starts sequential evaluation, all arguments have already been evaluated.Through@{conds}@x
evaluates all arguments before passing them toAnd
$\endgroup$And
isAnd[arg1, arg2, arg3]
and notAnd[{arg1, arg2, arg2}]
. Observe:And[Print[1]; False, Print[2]; False]
, more conveniently written as(Print[1]; False) && (Print[2]; False)
. The second argument never gets evaluated. $\endgroup$