From f09ae23cf977a418a037f6597c1be4aa48a5ef36 Mon Sep 17 00:00:00 2001 From: Pol Dellaiera Date: Wed, 30 Dec 2020 13:21:38 +0100 Subject: [PATCH 1/9] tests: Reproduce issue in a test. --- spec/loophp/collection/CollectionSpec.php | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/spec/loophp/collection/CollectionSpec.php b/spec/loophp/collection/CollectionSpec.php index 5f2765fc3..1e0f1ec97 100644 --- a/spec/loophp/collection/CollectionSpec.php +++ b/spec/loophp/collection/CollectionSpec.php @@ -3034,6 +3034,34 @@ public function it_can_zip(): void ->shouldIterateAs([[1, 'A'], [2, 'B'], [3, 'C'], [4, 'D'], [5, 'E']]); } + /** + * @see https://github.com/loophp/collection/issues/57 + */ + public function it_fix_bug_57() + { + $input = array_combine(range(1, 26), range('a', 'z')); + + $collection = $this::fromIterable($input); + + $collection + ->key() + ->shouldReturn(1); + + $collection + ->current() + ->shouldReturn('a'); + + $last = $collection->last(); + + $last + ->key() + ->shouldReturn(26); + + $last + ->current() + ->shouldReturn('z'); + } + public function it_is_initializable(): void { $this->shouldHaveType(Collection::class); From 804b4de9ec746f6753092a4380fdbddc2eb85cf4 Mon Sep 17 00:00:00 2001 From: Pol Dellaiera Date: Wed, 30 Dec 2020 13:26:03 +0100 Subject: [PATCH 2/9] fix: Simple fix which should fix the issue. --- src/Operation/Last.php | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/Operation/Last.php b/src/Operation/Last.php index 0d8d5ffe0..4af53a81f 100644 --- a/src/Operation/Last.php +++ b/src/Operation/Last.php @@ -4,7 +4,6 @@ namespace loophp\collection\Operation; -use CachingIterator; use Closure; use EmptyIterator; use Generator; @@ -29,20 +28,15 @@ public function __invoke(): Closure * @psalm-return Generator */ static function (Iterator $iterator): Generator { - if (!$iterator->valid()) { - return new EmptyIterator(); - } - - $cachingIterator = new CachingIterator($iterator, CachingIterator::FULL_CACHE); + $isEmpty = 1; - while ($iterator->valid()) { - $cachingIterator->next(); + foreach ($iterator as $key => $current) { + $isEmpty = 0; } - /** @psalm-var TKey $key */ - $key = $cachingIterator->key(); - /** @psalm-var T $current */ - $current = $cachingIterator->current(); + if (1 === $isEmpty) { + return new EmptyIterator(); + } return yield $key => $current; }; From c8d66c1f07008ec2fd593da25d069fb6de470c9f Mon Sep 17 00:00:00 2001 From: Pol Dellaiera Date: Wed, 30 Dec 2020 13:42:22 +0100 Subject: [PATCH 3/9] refactor: Use Foreach loops." This reverts commits: - 47e0f5e872297802fa0748b1381bf684b6d261ba - c59cea9b56b8c8ef97c1a0cf87eb8863e3be5e82. --- src/Operation/Apply.php | 9 +++------ src/Operation/Associate.php | 9 +++------ src/Operation/Chunk.php | 8 +++----- src/Operation/Collapse.php | 8 +++----- src/Operation/Contains.php | 6 ++---- src/Operation/DropWhile.php | 2 +- src/Operation/Duplicate.php | 11 ++++------- src/Operation/Flatten.php | 13 +++++-------- src/Operation/Flip.php | 4 ++-- src/Operation/Intersperse.php | 7 ++----- src/Operation/Map.php | 7 ++----- src/Operation/Normalize.php | 4 ++-- src/Operation/Pad.php | 4 ++-- src/Operation/Reduction.php | 7 ++----- src/Operation/Since.php | 5 +---- src/Operation/Split.php | 11 ++++------- src/Operation/TakeWhile.php | 5 +---- src/Operation/Transpose.php | 7 ++----- src/Operation/Unpair.php | 6 +++--- src/Operation/Until.php | 5 +---- src/Operation/Window.php | 6 +++--- 21 files changed, 51 insertions(+), 93 deletions(-) diff --git a/src/Operation/Apply.php b/src/Operation/Apply.php index 9d801de9f..72afc2ca9 100644 --- a/src/Operation/Apply.php +++ b/src/Operation/Apply.php @@ -33,19 +33,16 @@ public function __invoke(): Closure * @psalm-return Generator */ static function (Iterator $iterator) use ($callbacks): Generator { - for (; $iterator->valid(); $iterator->next()) { - $key = $iterator->key(); - $current = $iterator->current(); - + foreach ($iterator as $key => $value) { foreach ($callbacks as $callback) { - if (true === $callback($current, $key)) { + if (true === $callback($value, $key)) { continue; } break; } - yield $key => $current; + yield $key => $value; } }; } diff --git a/src/Operation/Associate.php b/src/Operation/Associate.php index a18c9702f..3ec2b1892 100644 --- a/src/Operation/Associate.php +++ b/src/Operation/Associate.php @@ -68,15 +68,12 @@ static function (Iterator $iterator) use ($callbackForKeys, $callbackForValues): */ static fn ($initial, callable $callback, int $callbackId, Iterator $iterator) => $callback($initial, $key, $value, $iterator); - for (; $iterator->valid(); $iterator->next()) { - $key = $iterator->key(); - $current = $iterator->current(); - + foreach ($iterator as $key => $value) { /** @psalm-var Generator $k */ - $k = FoldLeft::of()($callbackFactory($key)($current))($key)(new ArrayIterator($callbackForKeys)); + $k = FoldLeft::of()($callbackFactory($key)($value))($key)(new ArrayIterator($callbackForKeys)); /** @psalm-var Generator $c */ - $c = FoldLeft::of()($callbackFactory($key)($current))($current)(new ArrayIterator($callbackForValues)); + $c = FoldLeft::of()($callbackFactory($key)($value))($value)(new ArrayIterator($callbackForValues)); yield $k->current() => $c->current(); } diff --git a/src/Operation/Chunk.php b/src/Operation/Chunk.php index c0cea9b8f..1983f001c 100644 --- a/src/Operation/Chunk.php +++ b/src/Operation/Chunk.php @@ -41,15 +41,13 @@ static function (Iterator $iterator) use ($sizes): Generator { $values = []; - for (; $iterator->valid(); $iterator->next()) { - $current = $iterator->current(); - + foreach ($iterator as $value) { if (0 >= $sizesIterator->current()) { return new EmptyIterator(); } if (count($values) !== $sizesIterator->current()) { - $values[] = $current; + $values[] = $value; continue; } @@ -58,7 +56,7 @@ static function (Iterator $iterator) use ($sizes): Generator { yield $values; - $values = [$current]; + $values = [$value]; } return yield $values; diff --git a/src/Operation/Collapse.php b/src/Operation/Collapse.php index 386009944..7b6bddae8 100644 --- a/src/Operation/Collapse.php +++ b/src/Operation/Collapse.php @@ -27,14 +27,12 @@ public function __invoke(): Closure * @psalm-return Generator */ static function (Iterator $iterator): Generator { - for (; $iterator->valid(); $iterator->next()) { - $current = $iterator->current(); - - if (false === is_iterable($current)) { + foreach ($iterator as $value) { + if (false === is_iterable($value)) { continue; } - yield from $current; + yield from $value; } }; } diff --git a/src/Operation/Contains.php b/src/Operation/Contains.php index 8035fe1dd..492218851 100644 --- a/src/Operation/Contains.php +++ b/src/Operation/Contains.php @@ -37,11 +37,9 @@ static function (Iterator $iterator) use ($values): Generator { // yield count($values) === Intersect::of()(...$values)($iterator); // But it would not be very optimal because it would have to traverse // the whole iterator. - for (; $iterator->valid(); $iterator->next()) { - $current = $iterator->current(); - + foreach ($iterator as $value) { foreach ($values as $k => $v) { - if ($v === $current) { + if ($v === $value) { unset($values[$k]); } diff --git a/src/Operation/DropWhile.php b/src/Operation/DropWhile.php index 992b33829..d89537887 100644 --- a/src/Operation/DropWhile.php +++ b/src/Operation/DropWhile.php @@ -24,7 +24,7 @@ public function __invoke(): Closure { return /** - * @psalm-param callable(T, TKey, Iterator): bool ...$callbacks + * @psalm-param callable(T, TKey, Iterator):bool $callback * * @psalm-return Closure(Iterator): Generator */ diff --git a/src/Operation/Duplicate.php b/src/Operation/Duplicate.php index 47618263c..d2a373448 100644 --- a/src/Operation/Duplicate.php +++ b/src/Operation/Duplicate.php @@ -31,15 +31,12 @@ public function __invoke(): Closure static function (Iterator $iterator): Generator { $stack = []; - for (; $iterator->valid(); $iterator->next()) { - $key = $iterator->key(); - $current = $iterator->current(); - - if (true === in_array($current, $stack, true)) { - yield $key => $current; + foreach ($iterator as $key => $value) { + if (true === in_array($value, $stack, true)) { + yield $key => $value; } - $stack[] = $current; + $stack[] = $value; } }; } diff --git a/src/Operation/Flatten.php b/src/Operation/Flatten.php index 9de9634d9..ed8e28508 100644 --- a/src/Operation/Flatten.php +++ b/src/Operation/Flatten.php @@ -30,12 +30,9 @@ public function __invoke(): Closure * @psalm-param Iterator $iterator */ static function (Iterator $iterator) use ($depth): Generator { - for (; $iterator->valid(); $iterator->next()) { - $key = $iterator->key(); - $current = $iterator->current(); - - if (false === is_iterable($current)) { - yield $key => $current; + foreach ($iterator as $key => $value) { + if (false === is_iterable($value)) { + yield $key => $value; continue; } @@ -44,10 +41,10 @@ static function (Iterator $iterator) use ($depth): Generator { /** @psalm-var callable(Iterator): Generator $flatten */ $flatten = Flatten::of()($depth - 1); - $current = $flatten(new IterableIterator($current)); + $value = $flatten(new IterableIterator($value)); } - yield from $current; + yield from $value; } }; } diff --git a/src/Operation/Flip.php b/src/Operation/Flip.php index 2b977f6eb..8516cf7ea 100644 --- a/src/Operation/Flip.php +++ b/src/Operation/Flip.php @@ -16,7 +16,7 @@ final class Flip extends AbstractOperation { /** - * @psalm-return Closure(Iterator): Generator + * @psalm-return Closure(Iterator): Closure(Iterator): Generator */ public function __invoke(): Closure { @@ -40,7 +40,7 @@ public function __invoke(): Closure */ static fn ($carry, $key, $value) => $key; - /** @psalm-var Closure(Iterator): Generator $associate */ + /** @psalm-var Closure(Iterator): Generator $associate */ $associate = Associate::of()($callbackForKeys)($callbackForValues); // Point free style. diff --git a/src/Operation/Intersperse.php b/src/Operation/Intersperse.php index a676ed791..d9c727446 100644 --- a/src/Operation/Intersperse.php +++ b/src/Operation/Intersperse.php @@ -55,15 +55,12 @@ static function (Iterator $iterator) use ($element, $atEvery, $startAt): Generat ); } - for (; $iterator->valid(); $iterator->next()) { - $key = $iterator->key(); - $current = $iterator->current(); - + foreach ($iterator as $key => $value) { if (0 === $startAt++ % $atEvery) { yield $element; } - yield $key => $current; + yield $key => $value; } }; } diff --git a/src/Operation/Map.php b/src/Operation/Map.php index d882186b0..cdfcb91f2 100644 --- a/src/Operation/Map.php +++ b/src/Operation/Map.php @@ -51,11 +51,8 @@ static function (Iterator $iterator) use ($callbacks): Generator { */ static fn ($carry, callable $callback) => $callback($carry, $key, $iterator); - for (; $iterator->valid(); $iterator->next()) { - $key = $iterator->key(); - $current = $iterator->current(); - - yield $key => array_reduce($callbacks, $callbackFactory($key), $current); + foreach ($iterator as $key => $value) { + yield $key => array_reduce($callbacks, $callbackFactory($key), $value); } }; } diff --git a/src/Operation/Normalize.php b/src/Operation/Normalize.php index c11f2086c..194d4a2d9 100644 --- a/src/Operation/Normalize.php +++ b/src/Operation/Normalize.php @@ -27,8 +27,8 @@ public function __invoke(): Closure * @psalm-return Generator */ static function (Iterator $iterator): Generator { - for (; $iterator->valid(); $iterator->next()) { - yield $iterator->current(); + foreach ($iterator as $value) { + yield $value; } }; } diff --git a/src/Operation/Pad.php b/src/Operation/Pad.php index 6156bfbc7..b78585120 100644 --- a/src/Operation/Pad.php +++ b/src/Operation/Pad.php @@ -40,10 +40,10 @@ public function __invoke(): Closure static function (Iterator $iterator) use ($size, $padValue): Generator { $y = 0; - for (; $iterator->valid(); $iterator->next()) { + foreach ($iterator as $key => $value) { ++$y; - yield $iterator->key() => $iterator->current(); + yield $key => $value; } while ($y++ < $size) { diff --git a/src/Operation/Reduction.php b/src/Operation/Reduction.php index 046e94b8b..62561447d 100644 --- a/src/Operation/Reduction.php +++ b/src/Operation/Reduction.php @@ -42,11 +42,8 @@ public function __invoke(): Closure * @psalm-return Generator */ static function (Iterator $iterator) use ($callback, $initial): Generator { - for (; $iterator->valid(); $iterator->next()) { - $key = $iterator->key(); - $current = $iterator->current(); - - yield $key => ($initial = $callback($initial, $current, $key, $iterator)); + foreach ($iterator as $key => $value) { + yield $key => ($initial = $callback($initial, $value, $key, $iterator)); } }; } diff --git a/src/Operation/Since.php b/src/Operation/Since.php index 1c671710a..4d76188aa 100644 --- a/src/Operation/Since.php +++ b/src/Operation/Since.php @@ -63,10 +63,7 @@ static function (Iterator $iterator) use ($callbacks): Generator { */ static fn (bool $carry, callable $callable): bool => ($callable($current, $key, $iterator)) ? $carry : false; - for (; $iterator->valid(); $iterator->next()) { - $key = $iterator->key(); - $current = $iterator->current(); - + foreach ($iterator as $key => $current) { $result = array_reduce( $callbacks, $reducerCallback($key)($current)($iterator), diff --git a/src/Operation/Split.php b/src/Operation/Split.php index 2ba9bbc42..c4c22f71a 100644 --- a/src/Operation/Split.php +++ b/src/Operation/Split.php @@ -63,14 +63,11 @@ static function (Iterator $iterator) use ($type, $callbacks): Generator { */ static fn (bool $carry, callable $callback): bool => $callback($value, $key) || $carry; - for (; $iterator->valid(); $iterator->next()) { - $key = $iterator->key(); - $current = $iterator->current(); - - $callbackReturn = array_reduce($callbacks, $reducer($key)($current), false); + foreach ($iterator as $key => $value) { + $callbackReturn = array_reduce($callbacks, $reducer($key)($value), false); if (Splitable::AFTER === $type) { - $carry[] = $current; + $carry[] = $value; } if (Splitable::REMOVE === $type && true === $callbackReturn) { @@ -88,7 +85,7 @@ static function (Iterator $iterator) use ($type, $callbacks): Generator { } if (Splitable::BEFORE === $type || Splitable::REMOVE === $type) { - $carry[] = $current; + $carry[] = $value; } } diff --git a/src/Operation/TakeWhile.php b/src/Operation/TakeWhile.php index 01cd280c2..650216c0a 100644 --- a/src/Operation/TakeWhile.php +++ b/src/Operation/TakeWhile.php @@ -63,10 +63,7 @@ static function (Iterator $iterator) use ($callbacks): Generator { */ static fn (bool $carry, callable $callable): bool => ($callable($current, $key, $iterator)) ? $carry : false; - for (; $iterator->valid(); $iterator->next()) { - $key = $iterator->key(); - $current = $iterator->current(); - + foreach ($iterator as $key => $current) { $result = array_reduce( $callbacks, $reducerCallback($key)($current)($iterator), diff --git a/src/Operation/Transpose.php b/src/Operation/Transpose.php index c58b03e4c..f9a0a8e9d 100644 --- a/src/Operation/Transpose.php +++ b/src/Operation/Transpose.php @@ -28,7 +28,7 @@ public function __invoke(): Closure * * @psalm-return Generator> */ - static function (Iterator $iterator): Generator { + static function (Iterator $iterator): Iterator { $mit = new MultipleIterator(MultipleIterator::MIT_NEED_ANY); foreach ($iterator as $iterableIterator) { @@ -54,10 +54,7 @@ static function (Iterator $iterator): Generator { */ static fn (array $carry, array $key, array $value): array => $value; - /** @psalm-var Closure(Iterator): Generator> $associate */ - $associate = Associate::of()($callbackForKeys)($callbackForValues); - - return $associate($mit); + return Associate::of()($callbackForKeys)($callbackForValues)($mit); }; } } diff --git a/src/Operation/Unpair.php b/src/Operation/Unpair.php index 24c04e472..ead83cefd 100644 --- a/src/Operation/Unpair.php +++ b/src/Operation/Unpair.php @@ -27,10 +27,10 @@ public function __invoke(): Closure * @psalm-return Generator */ static function (Iterator $iterator): Generator { - for (; $iterator->valid(); $iterator->next()) { - yield $iterator->key(); + foreach ($iterator as $key => $value) { + yield $key; - yield $iterator->current(); + yield $value; } }; } diff --git a/src/Operation/Until.php b/src/Operation/Until.php index dc98f1aa3..9315e6e0c 100644 --- a/src/Operation/Until.php +++ b/src/Operation/Until.php @@ -63,10 +63,7 @@ static function (Iterator $iterator) use ($callbacks): Generator { */ static fn (bool $carry, callable $callable): bool => ($callable($current, $key, $iterator)) ? $carry : false; - for (; $iterator->valid(); $iterator->next()) { - $key = $iterator->key(); - $current = $iterator->current(); - + foreach ($iterator as $key => $current) { yield $key => $current; $result = array_reduce( diff --git a/src/Operation/Window.php b/src/Operation/Window.php index 8243e3783..01121f5e9 100644 --- a/src/Operation/Window.php +++ b/src/Operation/Window.php @@ -43,11 +43,11 @@ static function (Iterator $iterator) use ($size): Generator { /** @psalm-var list $stack */ $stack = []; - for (; $iterator->valid(); $iterator->next()) { + foreach ($iterator as $key => $current) { // @todo Should we use Pack ? - $stack[$iterator->key()] = $iterator->current(); + $stack[$key] = $current; - yield $iterator->key() => $stack = array_slice($stack, $size); + yield $key => $stack = array_slice($stack, $size); } }; } From e1d91ec45955777b0b2e25d26c8dadd6d03013d1 Mon Sep 17 00:00:00 2001 From: Pol Dellaiera Date: Wed, 30 Dec 2020 13:51:09 +0100 Subject: [PATCH 4/9] refactor: Simplify operations. --- src/Operation/Drop.php | 6 +++--- src/Operation/ScanLeft.php | 27 ++++++++------------------- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/src/Operation/Drop.php b/src/Operation/Drop.php index aba55efac..56c091dc9 100644 --- a/src/Operation/Drop.php +++ b/src/Operation/Drop.php @@ -32,12 +32,12 @@ public function __invoke(): Closure * * @psalm-return Generator */ - static function (Iterator $iterator) use ($offsets): Generator { - if (!$iterator->valid()) { + static function (Iterator $iterator) use ($offsets): Iterator { + if (false === $iterator->valid()) { return new EmptyIterator(); } - return yield from new LimitIterator($iterator, array_sum($offsets)); + return new LimitIterator($iterator, array_sum($offsets)); }; } } diff --git a/src/Operation/ScanLeft.php b/src/Operation/ScanLeft.php index 3d3d6bf29..c0a88c513 100644 --- a/src/Operation/ScanLeft.php +++ b/src/Operation/ScanLeft.php @@ -35,25 +35,14 @@ public function __invoke(): Closure * * @psalm-return Closure(Iterator): Generator */ - static fn ($initial = null): Closure => - /** - * @psalm-param Iterator $iterator - * - * @psalm-return Generator - */ - static function (Iterator $iterator) use ($callback, $initial): Generator { - // @todo: See if we cannot find a better way to do this. - if (false === $iterator->valid()) { - return yield from []; - } + static function ($initial = null) use ($callback): Closure { + /** @psalm-var Closure(Iterator): Generator $pipe */ + $pipe = Pipe::of()( + Reduction::of()($callback)($initial), + Prepend::of()($initial) + ); - /** @psalm-var Closure(Iterator): Generator $pipe */ - $pipe = Pipe::of()( - Reduction::of()($callback)($initial), - Prepend::of()($initial) - ); - - return yield from $pipe($iterator); - }; + return $pipe; + }; } } From d8a82a55ec83cd7eaa50d64cfa879cb137c39ed4 Mon Sep 17 00:00:00 2001 From: Pol Dellaiera Date: Wed, 30 Dec 2020 13:51:16 +0100 Subject: [PATCH 5/9] tests: Update tests. --- spec/loophp/collection/CollectionSpec.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/loophp/collection/CollectionSpec.php b/spec/loophp/collection/CollectionSpec.php index 1e0f1ec97..0789bbfdc 100644 --- a/spec/loophp/collection/CollectionSpec.php +++ b/spec/loophp/collection/CollectionSpec.php @@ -754,7 +754,7 @@ public function it_can_every(): void $this::empty() ->every($callback) - ->shouldIterateAs([]); + ->shouldIterateAs([true]); $this::fromIterable(range(0, 10)) ->every( @@ -2028,7 +2028,7 @@ public function it_can_scanleft(): void $this::fromIterable([]) ->scanLeft($callback, 3) - ->shouldIterateAs([]); + ->shouldIterateAs([0 => 3]); } public function it_can_scanleft1(): void From 77debe9b773382d9301dc6030e1c487e01d9edef Mon Sep 17 00:00:00 2001 From: Pol Dellaiera Date: Wed, 30 Dec 2020 14:06:45 +0100 Subject: [PATCH 6/9] docs: Update documentation. --- docs/pages/api.rst | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/pages/api.rst b/docs/pages/api.rst index 08589b3f6..6973e3bc7 100644 --- a/docs/pages/api.rst +++ b/docs/pages/api.rst @@ -561,6 +561,15 @@ Signature: ``Collection::every(callable $callback);`` ->every($callback) ->current(); // true + Collection::fromIterable(range(0, 10)) + ->append(21) + ->every($callback) + ->current(); // false + + Collection::fromIterable([]) + ->every($callback) + ->current(); // true + explode ~~~~~~~ @@ -1434,8 +1443,8 @@ Signature: ``Collection::scanLeft(callable $callback, $initial = null);`` ->normalize(); // [64 ,16 ,8 ,2] Collection::empty() - ->scanLeft($callback, 3) - ->normalize(); // [3] + ->scanLeft($callback, 3); // [0 => 3] + scanLeft1 ~~~~~~~~~ From 09d0531da9476bc805f1e7cafefda0167a2fdfcb Mon Sep 17 00:00:00 2001 From: Pol Dellaiera Date: Wed, 30 Dec 2020 14:07:14 +0100 Subject: [PATCH 7/9] docs: Update typing information. --- src/Operation/Drop.php | 7 +++---- src/Operation/Last.php | 13 ++++++------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/Operation/Drop.php b/src/Operation/Drop.php index 56c091dc9..e1002ef95 100644 --- a/src/Operation/Drop.php +++ b/src/Operation/Drop.php @@ -6,7 +6,6 @@ use Closure; use EmptyIterator; -use Generator; use Iterator; use LimitIterator; @@ -18,19 +17,19 @@ final class Drop extends AbstractOperation { /** - * @psalm-return Closure(int...): Closure(Iterator): Generator + * @psalm-return Closure(int...): Closure(Iterator): Iterator */ public function __invoke(): Closure { return /** - * @psalm-return Closure(Iterator): Generator + * @psalm-return Closure(Iterator): Iterator */ static fn (int ...$offsets): Closure => /** * @psalm-param Iterator $iterator * - * @psalm-return Generator + * @psalm-return Iterator */ static function (Iterator $iterator) use ($offsets): Iterator { if (false === $iterator->valid()) { diff --git a/src/Operation/Last.php b/src/Operation/Last.php index 4af53a81f..16cc3c1cf 100644 --- a/src/Operation/Last.php +++ b/src/Operation/Last.php @@ -6,7 +6,6 @@ use Closure; use EmptyIterator; -use Generator; use Iterator; /** @@ -17,7 +16,7 @@ final class Last extends AbstractOperation { /** - * @psalm-return Closure(Iterator): Generator + * @psalm-return Closure(Iterator): Iterator */ public function __invoke(): Closure { @@ -25,16 +24,16 @@ public function __invoke(): Closure /** * @psalm-param Iterator $iterator * - * @psalm-return Generator + * @psalm-return Iterator */ - static function (Iterator $iterator): Generator { - $isEmpty = 1; + static function (Iterator $iterator): Iterator { + $isEmpty = true; foreach ($iterator as $key => $current) { - $isEmpty = 0; + $isEmpty = false; } - if (1 === $isEmpty) { + if (true === $isEmpty) { return new EmptyIterator(); } From 9472d03836e08e03b03a35ea4ee0b589a822ac47 Mon Sep 17 00:00:00 2001 From: Pol Dellaiera Date: Wed, 30 Dec 2020 14:24:54 +0100 Subject: [PATCH 8/9] tests: Update tests. --- spec/loophp/collection/Operation/CurrentSpec.php | 3 +-- spec/loophp/collection/Operation/LimitSpec.php | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/spec/loophp/collection/Operation/CurrentSpec.php b/spec/loophp/collection/Operation/CurrentSpec.php index 4ef7a220a..a75b233ec 100644 --- a/spec/loophp/collection/Operation/CurrentSpec.php +++ b/spec/loophp/collection/Operation/CurrentSpec.php @@ -18,8 +18,7 @@ public function it_can_get_current() $this ->__invoke()(0)($iterator) - ->current() - ->shouldReturn('a'); + ->shouldIterateAs(['a']); $this ->__invoke()(0)($iterator) diff --git a/spec/loophp/collection/Operation/LimitSpec.php b/spec/loophp/collection/Operation/LimitSpec.php index 6c5bdadce..c11fce5c6 100644 --- a/spec/loophp/collection/Operation/LimitSpec.php +++ b/spec/loophp/collection/Operation/LimitSpec.php @@ -33,8 +33,7 @@ public function it_can_set_an_offset() $this ->__invoke()(1)(2)($iterator) - ->current() - ->shouldReturn('c'); + ->shouldIterateAs([2 => 'c']); $this ->__invoke()(2)(2)($iterator) From a7b6a9c8964cfdb26b080844bfd8c1eb0970dc89 Mon Sep 17 00:00:00 2001 From: Pol Dellaiera Date: Wed, 30 Dec 2020 14:25:21 +0100 Subject: [PATCH 9/9] refactor: Return instead of yield. --- src/Operation/Filter.php | 11 +++++------ src/Operation/Head.php | 19 +++++++++++++------ src/Operation/Limit.php | 11 +++++------ src/Operation/Pipe.php | 14 +++++++------- src/Operation/ScanLeft1.php | 4 ++-- 5 files changed, 32 insertions(+), 27 deletions(-) diff --git a/src/Operation/Filter.php b/src/Operation/Filter.php index c00468aef..f197214a0 100644 --- a/src/Operation/Filter.php +++ b/src/Operation/Filter.php @@ -6,7 +6,6 @@ use CallbackFilterIterator; use Closure; -use Generator; use Iterator; /** @@ -19,7 +18,7 @@ final class Filter extends AbstractOperation { /** - * @psalm-return Closure(callable(T , TKey , Iterator ): bool ...):Closure (Iterator): Generator + * @psalm-return Closure(callable(T , TKey , Iterator ): bool ...): Closure (Iterator): Iterator */ public function __invoke(): Closure { @@ -27,15 +26,15 @@ public function __invoke(): Closure /** * @psalm-param callable(T, TKey, Iterator): bool ...$callbacks * - * @psalm-return Closure(Iterator): Generator + * @psalm-return Closure(Iterator): Iterator */ static fn (callable ...$callbacks): Closure => /** * @psalm-param Iterator $iterator * - * @psalm-return Generator + * @psalm-return Iterator */ - static function (Iterator $iterator) use ($callbacks): Generator { + static function (Iterator $iterator) use ($callbacks): Iterator { $defaultCallback = /** * @param mixed $value @@ -52,7 +51,7 @@ static function (Iterator $iterator) use ($callbacks): Generator { [$defaultCallback] : $callbacks; - return yield from array_reduce( + return array_reduce( $callbacks, static fn (Iterator $carry, callable $callback): CallbackFilterIterator => new CallbackFilterIterator($carry, $callback), $iterator diff --git a/src/Operation/Head.php b/src/Operation/Head.php index f9dfe7eac..bd8efad75 100644 --- a/src/Operation/Head.php +++ b/src/Operation/Head.php @@ -6,7 +6,6 @@ use Closure; use EmptyIterator; -use Generator; use Iterator; /** @@ -17,7 +16,7 @@ final class Head extends AbstractOperation { /** - * @psalm-return Closure(Iterator): Generator + * @psalm-return Closure(Iterator): Iterator */ public function __invoke(): Closure { @@ -25,14 +24,22 @@ public function __invoke(): Closure /** * @psalm-param Iterator $iterator * - * @psalm-return Generator + * @psalm-return Iterator */ - static function (Iterator $iterator): Generator { - if (!$iterator->valid()) { + static function (Iterator $iterator): Iterator { + $isEmpty = true; + + foreach ($iterator as $key => $current) { + $isEmpty = false; + + break; + } + + if (true === $isEmpty) { return new EmptyIterator(); } - return yield $iterator->key() => $iterator->current(); + return yield $key => $current; }; } } diff --git a/src/Operation/Limit.php b/src/Operation/Limit.php index 375518aac..a9ccc5a8e 100644 --- a/src/Operation/Limit.php +++ b/src/Operation/Limit.php @@ -5,7 +5,6 @@ namespace loophp\collection\Operation; use Closure; -use Generator; use Iterator; use LimitIterator; @@ -19,24 +18,24 @@ final class Limit extends AbstractOperation { /** - * @psalm-return Closure(int): Closure(int): Closure(Iterator): Generator + * @psalm-return Closure(int): Closure(int): Closure(Iterator): Iterator */ public function __invoke(): Closure { return /** - * @psalm-return Closure(int): Closure(Iterator): Generator + * @psalm-return Closure(int): Closure(Iterator): Iterator */ static fn (int $count = -1): Closure => /** - * @psalm-return Closure(Iterator): Generator + * @psalm-return Closure(Iterator): Iterator */ static fn (int $offset = 0): Closure => /** * @psalm-param Iterator $iterator * - * @psalm-return Generator + * @psalm-return Iterator */ - static fn (Iterator $iterator): Generator => yield from new LimitIterator($iterator, $offset, $count); + static fn (Iterator $iterator): Iterator => new LimitIterator($iterator, $offset, $count); } } diff --git a/src/Operation/Pipe.php b/src/Operation/Pipe.php index ab7192ea2..e0c687f4c 100644 --- a/src/Operation/Pipe.php +++ b/src/Operation/Pipe.php @@ -18,7 +18,7 @@ final class Pipe extends AbstractOperation { /** - * @psalm-return Closure(callable(Iterator ): Generator ...):Closure (Iterator): Generator + * @psalm-return Closure(callable(Iterator ): Iterator ...): Closure (Iterator): Iterator */ public function __invoke(): Closure { @@ -26,25 +26,25 @@ public function __invoke(): Closure /** * @psalm-param callable(Iterator): Generator ...$operations * - * @psalm-return Closure(Iterator): Generator + * @psalm-return Closure(Iterator): Iterator */ static fn (callable ...$operations): Closure => /** * @psalm-param Iterator $iterator * - * @psalm-return Generator + * @psalm-return Iterator */ - static function (Iterator $iterator) use ($operations): Generator { + static function (Iterator $iterator) use ($operations): Iterator { $callback = /** * @psalm-param Iterator $iterator - * @psalm-param callable(Iterator): Generator $fn + * @psalm-param callable(Iterator): Iterator $fn * - * @psalm-return Generator + * @psalm-return Iterator */ static fn (Iterator $iterator, callable $fn): Iterator => $fn($iterator); - return yield from array_reduce($operations, $callback, $iterator); + return array_reduce($operations, $callback, $iterator); }; } } diff --git a/src/Operation/ScanLeft1.php b/src/Operation/ScanLeft1.php index 16948fcac..dea8ad700 100644 --- a/src/Operation/ScanLeft1.php +++ b/src/Operation/ScanLeft1.php @@ -34,7 +34,7 @@ public function __invoke(): Closure * * @psalm-return Generator */ - static function (Iterator $iterator) use ($callback): Generator { + static function (Iterator $iterator) use ($callback): Iterator { $initial = $iterator->current(); /** @psalm-var Closure(Iterator):(Generator) $pipe */ @@ -44,7 +44,7 @@ static function (Iterator $iterator) use ($callback): Generator { Prepend::of()($initial) ); - return yield from $pipe($iterator); + return $pipe($iterator); }; } }