Hi Alex,

> > I've created a new RFC https://wiki.php.net/rfc/cachediterable adding 
> > CachedIterable,
> > which eagerly evaluates any iterable and contains an immutable copy of the 
> > keys and values of the iterable it was constructed from
> >
> >
> > Any other feedback unrelated to namespaces?
>
> Hi Tyson,
>
> I needed this feature a few years ago. In that case, the source was a 
> generator that was slowly generating data while fetching them from a 
> paginated API that had rate limits.
> The result wrapping iterator was used at runtime in multiple (hundreds) other 
> iterators that were processing elements in various ways (technical analysis 
> indicator on time series) and after that merged back with some 
> MultipleIterator.
>
> Just for reference, this is how the implementation in userland was and I was 
> happy with it as a solution:
> https://gist.github.com/drealecs/ad720b51219675a8f278b8534e99d7c7
>
> Not sure if it's useful but I thought I should share it as I noticed you 
> mentioned in your example for PolyfillIterator you chose not to use an 
> IteratorAggregate because complexity
> Was wondering how much inefficient this would be compared to the C 
> implementation.

That was for simplicity(shortness) of the RFC for people reading the polyfill.
I don't expect it to affect CPU timing or memory usage for large arrays in the 
polyfill.

Userland lazy iterable implementations could still benefit from having a 
CachedIterable around,
by replacing the lazy IteratorAggregate with a Cached Iterable when the end of 
iteration was detected.

> Also, the implementation having the ability to be lazy was important and I 
> think that should be the case here as well, by design, especially as we are 
> dealing with Generators.

We're dealing with the entire family of iterables, including but not limited to 
Generators, arrays, user-defined Traversables, etc.

I'd considered that but decided not to include it in the RFC's scope.
If I was designing that, it would be a separate class `LazyCachedIterable`.

Currently, `CachedIterable` has several useful properties:

1. Serialization/Unserializable behavior is predictable - if the object was 
constructed it can be safely serialized if keys/values can be serialized.
2. Iteration has no side effects (e.g. won't throw)
3. keyAt(int $offset) and so on have predictable behavior, good performance, 
and only one throwable type
4. Memory usage is small - this might also be the case for a LazyIterable 
depending on implementation choices/constraints.

Adding lazy iteration support would make it no longer have some of those 
properties.

While I'd be in favor of that if it was implemented correctly, I don't plan to 
work on implementing this until I know
if the addition of `CachedIterable` to a large family of iterable classes would 
pass.

CachedIterable has some immediate benefits on problems I was actively working 
on, such as:

1. Being able to represent iterable functions such as iterable_reverse()
2. Memory efficiency and time efficiency for iteration
3. Being something internal code could return for getIterator(), etc.

Regards,
Tyson

Reply via email to