7
$\begingroup$

And[f[1],f[2]] doesn't evaluate f[2] if f[1] is false, but And@@{f[1],f[2]} does.

How do I evaluate And@@(f/@list), or Or@@(f/@list) for that matter, without evaluating more than necessary of f/@list?

$\endgroup$
3
  • 7
    $\begingroup$ AllTrue[list, f] ? $\endgroup$ – ilian Mar 15 '20 at 14:39
  • $\begingroup$ Related: (124534) $\endgroup$ – Mr.Wizard Mar 16 '20 at 2:01
  • 4
    $\begingroup$ AllTrue is cleaner, but for reference: And @@ f /@ Hold @@ list $\endgroup$ – Mr.Wizard Mar 16 '20 at 2:38
6
$\begingroup$

How about using Block?:

f[a_] := a < 2
lst = Range[5]
Block[{f}, And @@ f /@ lst]

If you already have the explicit list at hand, you can simply use Unevaluated:

And @@ Unevaluated @ {f[1], f[2], f[3], f[4], f[5]}

If you don't even want to generate the expression And[f[1], f[2], …] in intermediate step, then I think it's better to avoid And:

Catch[If[! f @ #, Throw @ False] & /@ lst; True]

Similarly, Or @@ f /@ lst can be implemented as

Catch[If[f @ #, Throw @ True] & /@ lst; False]

For completeness, as mentioned by ilian and Blrp, AllTrue and AnyTrue seems to be the best choice since v10.0.

A simple test for all the methods under this question:

f[a_] := a < 250000
f2 = # < 250000 &;
lst = Range[500000];

Block[{f}, And @@ f /@ lst] // RepeatedTiming
(* {0.29, False} *)
Block[{f}, And @@ f2 /@ lst] // RepeatedTiming
(* {0.290, False} *)

Catch[If[! f @ #, Throw @ False] & /@ lst; True] // RepeatedTiming
(* {0.488, False} *)
Catch[If[! f2@ #, Throw @ False] & /@ lst; True] // RepeatedTiming
(* {0.4785, False} *)

Catch[Scan[If[! f @ #, Throw @ False] &, lst]; True] // RepeatedTiming
(* {0.3554, False} *)
Catch[Scan[If[! f2 @ #, Throw @ False] &, lst]; True] // RepeatedTiming
(* {0.352, False} *)

And @@ f /@ Hold @@ lst // RepeatedTiming
(* {0.231, False} *)
And @@ f2 /@ Hold @@ lst // RepeatedTiming
(* {0.194, False} *)

AllTrue[lst,f] // RepeatedTiming
(* {0.165, False} *)
AllTrue[lst,f2] // RepeatedTiming
(* {0.13, False} *)

Tested on v12.1.0. (Wolfram cloud, Android app. )

$\endgroup$
8
  • 2
    $\begingroup$ ilian's suggestion of AllTrue is another way, and most convenient in some circumstances such as built-in functions and unassigned pure functions. Add it, as well as AnyTrue, and I'll accept. $\endgroup$ – Blrp Mar 15 '20 at 22:32
  • 1
    $\begingroup$ @victor Seems that the new version is always released a bit earlier silently on Wolfram cloud. The blog post is coming soon, I believe. $\endgroup$ – xzczd Mar 16 '20 at 5:19
  • 1
    $\begingroup$ @xzczd that's cool - you can already browse the list of new feature etc. reference.wolframcloud.com/cloudplatform/guide/… $\endgroup$ – Victor K. Mar 16 '20 at 6:17
  • 1
    $\begingroup$ In the Ctach[Map[...]] construct, use Scan instead of Map as it doesn't generate the intermediate List like Map. $\endgroup$ – rcollyer Mar 16 '20 at 12:57
  • 1
    $\begingroup$ @rcollyer I used Map just for compactness, and didn't expect the generation of output slows down the code that much. Edited. Thx for the reminding. $\endgroup$ – xzczd Mar 17 '20 at 2:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.