Re: Proposal: Adding a RewindableKeyValueIterator type allowing mixed/repeated keys
| From: | tyson andre | Date: | Tue, 02 Feb 2021 14:59:25 +0000 |
| Subject: | Re: Proposal: Adding a RewindableKeyValueIterator type allowing mixed/repeated keys | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-113051@lists.php.net to get a copy of this message | ||
Hi internals,
> Currently, there don't seem to be any internal classes that can be used to store a copy of
> the keys and values of an arbitrary Traversable.
>
> - This would help in eagerly evaluating the result of a generator in a memory efficient way
> that could be exactly stored and reused
> e.g.
return $this->cachedResults ??= new
> \RewindableKeyValueIterator($this->innerResultsGenerator());
> https://externals.io/message/108767#108797
> - This would be useful to exactly represent the keys of sequences with repeated keys (e.g. ;Ù
> Çz±Ôÿá;:ðyield 'first'; yield 'second'; implicitly uses the
> key 0 twice.)
> - This would be convenient to have to differentiate between 1, '1', and true.
> - This would be useful if php were to add internal global functions that act on iterables and
> return Traversables with potentially repeated keys based on those iterables,
> e.g. map(), filter(), take(), flip(), etc
> - If PHP were to add more iterable methods, being able to save an immutable copy of a
> traversable's result would be useful for end users.
> - If PHP were to add a Map (ordered hash map with null/any scalar/arrays/objects as keys) class
> type in the future,
> and that implemented IteratorAggregate, the return type of getIterator() would need
> something like RewindableKeyValueIterator.
> - The lack of a relevant datatype is among the reasons why classes such as SplObjectStorage are
> still an Iterator instead of an IteratorAggregate. (and backwards compatibility)
>
> ```
> final class KeyValueSequenceIterator implements Iterator {
> // loop over all values in $values and store a copy, converting
> // references in top-level array values to non-references
> public function __construct(iterable $values) {...}
> public static function fromKeyValuePairs(iterable $entries): self {...} //
> fromKeyValuePairs([[$key1, $value1]])
> public function rewind(): void {...}
> public function next(): void {...}
> public function current(): mixed {...}
> public function key(): mixed {...}
> public function valid(): bool {...}
> // and __debugInfo, __clone(), etc.
> }
> ```
This has been updated - the preferred name is CachedIterable.
It turns out InternalIterator is generally more efficient,
and SplFixedArray is already using that.
The implementation is pretty much done - https://github.com/php/php-src/pull/6655
```
/**
* Internal class that can be used to eagerly evaluate and store a copy
* of the keys and values of an arbitrary Traversable.
* Keys can be any type, and keys can be repeated.
*/
final class CachedIterable implements IteratorAggregate, Countable
{
public function __construct(iterable $iterator) {}
public function getIterator(): InternalIterator {}
public function count(): int {}
public static function fromPairs(array $pairs): CachedIterable;
public function __serialize(): array {} // [$k1, $v1, $k2, $v2,...]
public function __unserialize(array $data): void {}
// useful for converting iterables back to values
public function keys(): array {}
public function values(): array {}
// useful to efficiently get offsets at the middle/end of a long iterable.
public function keyAt(int $offset): mixed {}
public function valueAt(int $offset): mixed {}
// dynamic properties are forbidden
}
```
Any other comments?
Thanks,
- Tyson