# How to evaluate the second argument of Cases only once

I'd like to find a fast but readable way to achieve the following:

Cases[RandomInteger[{AbsoluteTime["2001"], AbsoluteTime["2003"]}, 1000],
a_ /; a > AbsoluteTime["2002"]]


The correct result can be achieved much faster using with:

With[{d = AbsoluteTime["2002"]},
Cases[RandomInteger[{AbsoluteTime["2001"], AbsoluteTime["2003"]}, 1000],
a_ /; a > d]]


But this is not very readable. Is there a more readable way?

You could inject the value once with a Function instead of With.

Cases[RandomInteger[{AbsoluteTime["2001"], AbsoluteTime["2003"]},
1000], a_ /; a > #] &@ AbsoluteTime["2002"]


In V10, we can use named arguments, which is arguably [sic] more readable (and more typing):

Cases[RandomInteger[{AbsoluteTime["2001"], AbsoluteTime["2003"]},
1000], a_ /; a > #time] &[<|"time" -> AbsoluteTime["2002"]|>]


One could use Evaluate, although this would fail if a has a global value.

Cases[RandomInteger[{AbsoluteTime["2001"], AbsoluteTime["2003"]},
1000], a_ /; Evaluate[a > AbsoluteTime["2002"]]]


Protecting a with Block is a possibility, albeit a little cumbersome.

Block[{a},
Cases[RandomInteger[{AbsoluteTime["2001"], AbsoluteTime["2003"]},
1000], a_ /; Evaluate[a > AbsoluteTime["2002"]]]
]


I rather like the With construction and feel it's quite readable, but if you don't want to use it, how about:

Cases[
RandomInteger[{AbsoluteTime["2001"], AbsoluteTime["2003"]}, 1000]
- AbsoluteTime["2002"],
a_ /; a > 0
] +  AbsoluteTime["2002"]


or

Cases[
RandomInteger[{AbsoluteTime["2001"], AbsoluteTime["2003"]}, 1000]
- AbsoluteTime["2002"],
_?Positive
] +  AbsoluteTime["2002"]


or, with Select

Select[
RandomInteger[{AbsoluteTime["2001"], AbsoluteTime["2003"]}, 1000]
- AbsoluteTime["2002"],
Positive
] + AbsoluteTime["2002"]


which are all 200 times faster than your original and about as fast as With (though not particularly readable either).

For a different approach, how about a memoized version of AbsoluteTime:

at[x_] := at[x] = AbsoluteTime[x]

Cases[RandomInteger[{at["2001"], at["2003"]}, 1000], a_ /; a > at["2002"]]

• I like this (+1); it is about twice as fast as the original. I wonder whether this meets the OP's readability requirement, though. This is similar to starting with a With definition except that here the definition goes in global namespace. Just defining the value as a variable (together with your at in the random generator) is about two times faster still: d = AbsoluteTime["2002"]; Cases[RandomInteger[{at["2001"], at["2003"]}, 1000], a_ /; a > d]. – Sjoerd C. de Vries Oct 13 '15 at 21:59

With is designed to address the issue you bring up. The way to make your code readable is pick better variable names.

With[{midPoint = AbsoluteTime["2002"]},
Cases[RandomInteger[{AbsoluteTime["2001"], AbsoluteTime["2003"]}, 1000],
time_ /; time > midPoint]]