Lazy caching map()?

H. S. Teoh hsteoh at quickfur.ath.cx
Fri Mar 9 20:14:40 UTC 2018


On Fri, Mar 09, 2018 at 12:47:14PM -0700, Jonathan M Davis via Digitalmars-d wrote:
> On Friday, March 09, 2018 11:41:46 H. S. Teoh via Digitalmars-d wrote:
> > [...]  More precisely, given an array `T[] src` of source data and a
> > function func(T) that's pretty expensive to compute, return an
> > object `result` such that:
> >
> > - result[i] == func(src[i]), for 0 ≤ i < src.length.
> >
> > - If result[j] is never actually used, func(src[j]) is never invoked
> >   (lazy).
> >
> > - If result[j] is referenced multiple times, a cached value is returned
> >   after the first time, i.e., the result of func(src[j]) is cached, and
> >   func(src[j]) is never invoked more than once.
[...]
> > Can this be done using current Phobos primitives?
> 
> Wasn't that what std.algorithm.iteration.cache was supposed to solve?
> I've never used it, so I don't know how well it fits what you need,
> but IIRC, using it with map was basically the use that it was invented
> for.
[...]

The problem with cache() is that it does not return a random-access
range, and for my use case random-access is mandatory, because I cannot
predict ahead of time which indices will be used.  Worse yet, cache()
eagerly evaluates .front and .back, which is a no-no in my case (it
should not compute elements that are not asked for).

These two limitations defeats the entire purpose, since no RA means I
have to iterate to find the elements I want, and eager evaluation means
func() will be computed as I iterate, even if I never call .front. So
basically the entire result array will be computed.

It's also not trivial to extend cache() to handle random access, because
that means it has to allocate in order to store cached elements, whereas
the current implementation statically allocates space in the returned
range to store cached .front and .back elements.


T

-- 
An imaginary friend squared is a real enemy.


More information about the Digitalmars-d mailing list