Actually, the sample match I used as an example, the four tests complete in a flash, so memoizing will not speed things up. But if we can aviodavoid the testing of the latter three 1
, the whole process will be 4 times faster!
Additional and related examples
Here is an additional example that may help illustrate the inefficiency of reapplying the same test to the same element.
Replace[
{1.1, 2.2, 3, 4, 5},
{a___, x__?((Print[##]; IntegerQ[#]) &), y__} :>
{{a}, {x}, {y}}
]
1.1
1.1
1.1
1.1
2.2
2.2
2.2
3
{{1.1, 2.2}, {3}, {4, 5}}
This causes an algorithmic explosion in the time taken to process this pattern. In most applications it would be better if each element were only tested once. Observe that a test of a list of 200 elements performs almost twenty thousand tests:
i = 0;
MatchQ[N@Range[200], {a___, x__?((i++; IntegerQ[#]) &), y__}]
i
False
19900
This is not simply a matter handing the somewhat unusual case of a stateful test function (e.g. if the test function were (EvenQ[# + i++] &)
) as it is baked into immutable patterns as well:
Needs["GeneralUtilities`"]
BenchmarkPlot[
MatchQ[#, {a___, x__Integer, y__}] &,
RandomReal[99, #] &
, "IncludeFits" -> True
]