Streams and iterators
Using streams would certainly be one of the most elegant ways to do this. In any case, you will at least need an iterator for your sequence of numbers. The reason why an abstraction of an iterator is useful is because it separates the iteration over your sequence from the stuff you want to do with individual elements, so that you can implement them independently. It also inverses the control, since rather than doing an active iteration with your sequence, you get a next number on demand. This leads to a more modular code and better abstractions.
Iterator for a sequence of numbers
Here is one possibility. First, define an iterator for equidistant numbers:
ClearAll[makeIterator];
makeIterator[min_,max_,step_]:=
Module[{current=min},
With[{curr=current},
current=If[current+step<=max,current+step,Null];curr
]&
];
it can be used as
iter = makeIterator[1, 10, 1];
iter[]
iter[]
iter[]
(*
1
2
3
*)
Implementation of Or
Now, here is a possible implementation of Or
:
ClearAll[lazyOr];
lazyOr[iter_,f_]:=
While[
True,
(If[#1=!=Null,If[f[#1],Return[True]],Return[False]]&)[
iter[]
]
]
and here is how we can use it:
lazyOr[makeIterator[1, 10, 1], # > 10 &]
(* False *)
lazyOr[makeIterator[1, 10, 1], # > 9 &]
(* True *)
lazyOr[makeIterator[1, 10^10, 1], PrimeQ] // AbsoluteTiming
(* {0.000977, True} *)
Again, I want to stress that this is just a light-weight version of the lazy streams, where we had to make Or
less trivial because it should do the iteration. The full lazy stream construction postpones iteration until we actually request an element, and is more elegant in that sense.
f[n] is True
forn<<10^10
isn't thenOr
automatically True? Even if you do not know if it is so then one occurance is enough:Do[If[PrimeQ@i, Print[i]; Break[];], {i, 10^10}]
$\endgroup$f[n] is True
for somen << 10^10
. But yes, aDo
loop seems like what I need. I still wonder though, if there is a more functional way of approaching this problem. $\endgroup$