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$Andwill evaluate its arguments sequentially, returningFalseas soon as any argument isFalse. $\endgroup$Anditself doesn't evaluate arguments sequentially, but that by the time it starts sequential evaluation, all arguments have already been evaluated.Through@{conds}@xevaluates all arguments before passing them toAnd$\endgroup$AndisAnd[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$