From 6ce8ecfd386d7697ebe5ea230fd09e53b1dacb49 Mon Sep 17 00:00:00 2001 From: Pol Dellaiera Date: Wed, 26 Aug 2020 21:20:49 +0200 Subject: [PATCH] Convert Operations and Transformations into function object. --- src/Collection.php | 159 +++++++++--------- src/Contract/Operation.php | 5 - src/Contract/Transformation.php | 5 +- src/Contract/Transformation/Runable.php | 4 +- src/Contract/Transformation/Transformable.php | 10 +- src/Operation/Append.php | 20 +-- src/Operation/Apply.php | 36 ++-- src/Operation/Associate.php | 46 ++--- src/Operation/Cache.php | 25 ++- src/Operation/Chunk.php | 52 +++--- src/Operation/Column.php | 24 +-- src/Operation/Combinate.php | 61 +++---- src/Operation/Combine.php | 24 +-- src/Operation/Compact.php | 44 ++--- src/Operation/Cycle.php | 15 +- src/Operation/Diff.php | 20 +-- src/Operation/DiffKeys.php | 22 +-- src/Operation/Explode.php | 60 +++---- src/Operation/Filter.php | 44 ++--- src/Operation/First.php | 74 +++----- src/Operation/Flatten.php | 21 +-- src/Operation/Forget.php | 20 +-- src/Operation/Group.php | 87 +++++----- src/Operation/IfThenElse.php | 54 +++--- src/Operation/Intersect.php | 20 +-- src/Operation/IntersectKeys.php | 22 +-- src/Operation/Intersperse.php | 68 ++++---- src/Operation/Iterate.php | 38 ++--- src/Operation/Last.php | 72 +++----- src/Operation/Limit.php | 28 +-- src/Operation/Loop.php | 12 +- src/Operation/Map.php | 16 +- src/Operation/Merge.php | 20 +-- src/Operation/Normalize.php | 16 +- src/Operation/Nth.php | 34 ++-- src/Operation/Only.php | 22 +-- src/Operation/Pad.php | 43 ++--- src/Operation/Pair.php | 6 +- src/Operation/Pluck.php | 105 +++++------- src/Operation/Prepend.php | 20 +-- src/Operation/Product.php | 36 +--- src/Operation/RSample.php | 29 ++-- src/Operation/Random.php | 22 +-- src/Operation/Range.php | 23 ++- src/Operation/Reduction.php | 35 +--- src/Operation/Reverse.php | 2 +- src/Operation/Scale.php | 79 +++++---- src/Operation/Shuffle.php | 2 +- src/Operation/Since.php | 20 +-- src/Operation/Skip.php | 16 +- src/Operation/Slice.php | 38 ++--- src/Operation/Sort.php | 90 +++++----- src/Operation/Split.php | 67 ++++---- src/Operation/Tail.php | 2 +- src/Operation/Times.php | 41 ++--- src/Operation/Transpose.php | 24 +-- src/Operation/Until.php | 20 +-- src/Operation/Window.php | 46 ++--- src/Operation/Zip.php | 46 +++-- src/Transformation/All.php | 6 +- src/Transformation/Contains.php | 36 ++-- src/Transformation/Count.php | 7 +- src/Transformation/Falsy.php | 14 +- src/Transformation/FoldLeft.php | 49 ++---- src/Transformation/FoldRight.php | 44 ++--- src/Transformation/Get.php | 53 ++---- src/Transformation/Has.php | 42 ++--- src/Transformation/Implode.php | 57 +++---- src/Transformation/Nullsy.php | 17 +- src/Transformation/Reduce.php | 42 ++--- src/Transformation/Run.php | 39 ++--- src/Transformation/Transform.php | 45 ++--- src/Transformation/Truthy.php | 14 +- 73 files changed, 958 insertions(+), 1619 deletions(-) diff --git a/src/Collection.php b/src/Collection.php index 36f3b20ae..62066a950 100644 --- a/src/Collection.php +++ b/src/Collection.php @@ -8,7 +8,6 @@ use Generator; use loophp\collection\Contract\Collection as CollectionInterface; use loophp\collection\Contract\Operation; -use loophp\collection\Contract\Transformation; use loophp\collection\Iterator\ClosureIterator; use loophp\collection\Iterator\IterableIterator; use loophp\collection\Iterator\ResourceIterator; @@ -226,89 +225,89 @@ static function ($data): Generator { public function all(): array { - return $this->transform(new All()); + return $this->transform((new All())()); } public function append(...$items): CollectionInterface { - return $this->run(new Append(...$items)); + return $this->run((new Append())()(...$items)); } public function apply(callable ...$callables): CollectionInterface { - return $this->run(new Apply(...$callables)); + return $this->run((new Apply())()(...$callables)); } public function associate( ?callable $callbackForKeys = null, ?callable $callbackForValues = null ): CollectionInterface { - return $this->run(new Associate($callbackForKeys, $callbackForValues)); + return $this->run((new Associate())()($callbackForKeys)($callbackForValues)); } public function cache(?CacheItemPoolInterface $cache = null): CollectionInterface { - return $this->run(new Cache($cache ?? new ArrayAdapter())); + return $this->run((new Cache())()($cache ?? new ArrayAdapter())); } public function chunk(int ...$sizes): CollectionInterface { - return $this->run(new Chunk(...$sizes)); + return $this->run((new Chunk())()(...$sizes)); } public function collapse(): CollectionInterface { - return $this->run(new Collapse()); + return $this->run((new Collapse())()); } public function column($column): CollectionInterface { - return $this->run(new Column($column)); + return $this->run((new Column())()($column)); } public function combinate(?int $length = null): CollectionInterface { - return $this->run(new Combinate($length)); + return $this->run((new Combinate())()($length)); } public function combine(...$keys): CollectionInterface { - return $this->run(new Combine(...$keys)); + return $this->run((new Combine())()(...$keys)); } public function compact(...$values): CollectionInterface { - return $this->run(new Compact(...$values)); + return $this->run((new Compact())()(...$values)); } public function contains(...$value): bool { - return $this->transform(new Contains(...$value)); + return $this->transform((new Contains())()(...$value)); } public function count(): int { - return $this->transform(new Count()); + return $this->transform((new Count())()); } public function cycle(int $length = 0): CollectionInterface { - return $this->run(new Cycle($length)); + return $this->run((new Cycle())()($length)); } public function diff(...$values): CollectionInterface { - return $this->run(new Diff(...$values)); + return $this->run((new Diff())()(...$values)); } public function diffKeys(...$values): CollectionInterface { - return $this->run(new DiffKeys(...$values)); + return $this->run((new DiffKeys())()(...$values)); } public function distinct(): CollectionInterface { - return $this->run(new Distinct()); + return $this->run((new Distinct())()); } public static function empty(): Collection @@ -318,52 +317,52 @@ public static function empty(): Collection public function explode(...$explodes): CollectionInterface { - return $this->run(new Explode(...$explodes)); + return $this->run((new Explode())()(...$explodes)); } public function falsy(): bool { - return $this->transform(new Falsy()); + return $this->transform((new Falsy())()); } public function filter(callable ...$callbacks): CollectionInterface { - return $this->run(new Filter(...$callbacks)); + return $this->run((new Filter())()(...$callbacks)); } public function first(?callable $callback = null, int $size = 1): CollectionInterface { - return $this->run(new First($callback, $size)); + return $this->run((new First())()($callback)($size)); } public function flatten(int $depth = PHP_INT_MAX): CollectionInterface { - return $this->run(new Flatten($depth)); + return $this->run((new Flatten())()($depth)); } public function flip(): CollectionInterface { - return $this->run(new Flip()); + return $this->run((new Flip())()); } public function foldLeft(callable $callback, $initial = null) { - return $this->transform(new FoldLeft($callback, $initial)); + return $this->transform((new FoldLeft())()($callback)($initial)); } public function foldRight(callable $callback, $initial = null) { - return $this->transform(new FoldRight($callback, $initial)); + return $this->transform((new FoldRight())()($callback)($initial)); } public function forget(...$keys): CollectionInterface { - return $this->run(new Forget(...$keys)); + return $this->run((new Forget())()(...$keys)); } public function frequency(): CollectionInterface { - return $this->run(new Frequency()); + return $this->run((new Frequency())()); } public static function fromCallable(callable $callable, ...$parameters): Collection @@ -410,7 +409,7 @@ static function (string $string, string $delimiter): Generator { public function get($key, $default = null) { - return $this->transform(new Get($key, $default)); + return $this->transform((new Get())()($key)($default)); } public function getIterator(): ClosureIterator @@ -420,17 +419,17 @@ public function getIterator(): ClosureIterator public function group(?callable $callable = null): CollectionInterface { - return $this->run(new Group($callable)); + return $this->run((new Group())()($callable)); } public function has(callable $callback): bool { - return $this->transform(new Has($callback)); + return $this->transform((new Has())()($callback)); } public function head(): CollectionInterface { - return $this->run(new Head()); + return $this->run((new Head())()); } public function ifThenElse(callable $condition, callable $then, ?callable $else = null): CollectionInterface @@ -444,27 +443,27 @@ public function ifThenElse(callable $condition, callable $then, ?callable $else public function implode(string $glue = ''): string { - return $this->transform(new Implode($glue)); + return $this->transform((new Implode())()($glue)); } public function intersect(...$values): CollectionInterface { - return $this->run(new Intersect(...$values)); + return $this->run((new Intersect())()(...$values)); } public function intersectKeys(...$values): CollectionInterface { - return $this->run(new IntersectKeys(...$values)); + return $this->run((new IntersectKeys())()(...$values)); } public function intersperse($element, int $every = 1, int $startAt = 0): CollectionInterface { - return $this->run(new Intersperse($element, $every, $startAt)); + return $this->run((new Intersperse())()($element)($every)($startAt)); } public static function iterate(callable $callback, ...$parameters): CollectionInterface { - return (new self())->run(new Iterate($callback, $parameters)); + return (new self())->run((new Iterate())()($callback)($parameters)); } /** @@ -477,52 +476,52 @@ public function jsonSerialize(): array public function keys(): CollectionInterface { - return $this->run(new Keys()); + return $this->run((new Keys())()); } public function last(?callable $callback = null, int $size = 1): CollectionInterface { - return $this->run(new Last($callback, $size)); + return $this->run((new Last())()($callback)($size)); } public function limit(int $limit = -1, int $offset = 0): CollectionInterface { - return $this->run(new Limit($limit, $offset)); + return $this->run((new Limit())()($limit)($offset)); } public function loop(): CollectionInterface { - return $this->run(new Loop()); + return $this->run((new Loop())()); } public function map(callable ...$callbacks): CollectionInterface { - return $this->run(new Map(...$callbacks)); + return $this->run((new Map())()(...$callbacks)); } public function merge(iterable ...$sources): CollectionInterface { - return $this->run(new Merge(...$sources)); + return $this->run((new Merge())()(...$sources)); } public function normalize(): CollectionInterface { - return $this->run(new Normalize()); + return $this->run((new Normalize())()); } public function nth(int $step, int $offset = 0): CollectionInterface { - return $this->run(new Nth($step, $offset)); + return $this->run((new Nth())()($step)($offset)); } public function nullsy(): bool { - return $this->transform(new Nullsy()); + return $this->transform((new Nullsy())()); } public function only(...$keys): CollectionInterface { - return $this->run(new Only(...$keys)); + return $this->run((new Only())()(...$keys)); } public function pack(): CollectionInterface @@ -532,67 +531,67 @@ public function pack(): CollectionInterface public function pad(int $size, $value): CollectionInterface { - return $this->run(new Pad($size, $value)); + return $this->run((new Pad())()($size)($value)); } public function pair(): CollectionInterface { - return $this->run(new Pair()); + return $this->run((new Pair())()); } public function permutate(): CollectionInterface { - return $this->run(new Permutate()); + return $this->run((new Permutate())()); } public function pluck($pluck, $default = null): CollectionInterface { - return $this->run(new Pluck($pluck, $default)); + return $this->run((new Pluck())()($pluck)($default)); } public function prepend(...$items): CollectionInterface { - return $this->run(new Prepend(...$items)); + return $this->run((new Prepend())()(...$items)); } public function product(iterable ...$iterables): CollectionInterface { - return $this->run(new Product(...$iterables)); + return $this->run((new Product())()(...$iterables)); } public function random(int $size = 1): CollectionInterface { - return $this->run(new Random($size)); + return $this->run((new Random())()($size)); } public static function range(float $start = 0.0, float $end = INF, float $step = 1.0): CollectionInterface { - return (new self())->run(new Range($start, $end, $step)); + return (new self())->run((new Range())()($start)($end)($step)); } public function reduce(callable $callback, $initial = null) { - return $this->transform(new Reduce($callback, $initial)); + return $this->transform((new Reduce())()($callback)($initial)); } public function reduction(callable $callback, $initial = null): CollectionInterface { - return $this->run(new Reduction($callback, $initial)); + return $this->run((new Reduction())()($callback)($initial)); } public function reverse(): CollectionInterface { - return $this->run(new Reverse()); + return $this->run((new Reverse())()); } public function rsample(float $probability): CollectionInterface { - return $this->run(new RSample($probability)); + return $this->run((new RSample())()($probability)); } - public function run(Operation ...$operations) + public function run(callable ...$operations) { - return self::fromIterable((new Run(...$operations))($this->getIterator())); + return self::fromIterable((new Run())()(...$operations)($this->getIterator())); } public function scale( @@ -602,62 +601,62 @@ public function scale( float $wantedUpperBound = 1.0, float $base = 0.0 ): CollectionInterface { - return $this->run(new Scale($lowerBound, $upperBound, $wantedLowerBound, $wantedUpperBound, $base)); + return $this->run((new Scale())()($lowerBound)($upperBound)($wantedLowerBound)($wantedUpperBound)($base)); } public function shuffle(): CollectionInterface { - return $this->run(new Shuffle()); + return $this->run((new Shuffle())()); } public function since(callable ...$callbacks): CollectionInterface { - return $this->run(new Since(...$callbacks)); + return $this->run((new Since())()(...$callbacks)); } public function skip(int ...$counts): CollectionInterface { - return $this->run(new Skip(...$counts)); + return $this->run((new Skip())()(...$counts)); } public function slice(int $offset, int $length = -1): CollectionInterface { - return $this->run(new Slice($offset, $length)); + return $this->run((new Slice())()($offset)($length)); } public function sort(int $type = Operation\Sortable::BY_VALUES, ?callable $callback = null): CollectionInterface { - return $this->run(new Sort($type, $callback)); + return $this->run((new Sort())()($type)($callback)); } public function split(callable ...$callbacks): CollectionInterface { - return $this->run(new Split(...$callbacks)); + return $this->run((new Split())()(...$callbacks)); } public function tail(): CollectionInterface { - return $this->run(new Tail()); + return $this->run((new Tail())()); } public static function times(int $number = 0, ?callable $callback = null): CollectionInterface { - return (new self())->run(new Times($number, $callback)); + return (new self())->run((new Times())()($number)($callback)); } - public function transform(Transformation ...$transformers) + public function transform(callable ...$transformers) { - return (new Transform(...$transformers))($this->getIterator()); + return (new Transform())()(...$transformers)($this->getIterator()); } public function transpose(): CollectionInterface { - return $this->run(new Transpose()); + return $this->run((new Transpose())()); } public function truthy(): bool { - return $this->transform(new Truthy()); + return $this->transform((new Truthy())()); } public function unpack(): CollectionInterface @@ -667,22 +666,22 @@ public function unpack(): CollectionInterface public function unpair(): CollectionInterface { - return $this->run(new Unpair()); + return $this->run((new Unpair())()); } public function until(callable ...$callbacks): CollectionInterface { - return $this->run(new Until(...$callbacks)); + return $this->run((new Until())()(...$callbacks)); } public function unwrap(): CollectionInterface { - return $this->run(new Unwrap()); + return $this->run((new Unwrap())()); } public function window(int ...$length): CollectionInterface { - return $this->run(new Window(...$length)); + return $this->run((new Window())()(...$length)); } public static function with($data = [], ...$parameters): Collection @@ -692,11 +691,11 @@ public static function with($data = [], ...$parameters): Collection public function wrap(): CollectionInterface { - return $this->run(new Wrap()); + return $this->run((new Wrap())()); } public function zip(iterable ...$iterables): CollectionInterface { - return $this->run(new Zip(...$iterables)); + return $this->run((new Zip())()(...$iterables)); } } diff --git a/src/Contract/Operation.php b/src/Contract/Operation.php index 102c419d7..dfc7661d2 100644 --- a/src/Contract/Operation.php +++ b/src/Contract/Operation.php @@ -9,9 +9,4 @@ interface Operation { public function __invoke(): Closure; - - /** - * @return array - */ - public function getArguments(): array; } diff --git a/src/Contract/Transformation.php b/src/Contract/Transformation.php index 1b92ae10d..275c140c5 100644 --- a/src/Contract/Transformation.php +++ b/src/Contract/Transformation.php @@ -4,8 +4,6 @@ namespace loophp\collection\Contract; -use Iterator; - /** * @psalm-template TKey * @psalm-template TKey of array-key @@ -14,11 +12,10 @@ interface Transformation { /** - * @param iterable $collection * @psalm-param \Iterator $collection * * @return mixed * @psalm-return T|scalar|\Iterator|array|null */ - public function __invoke(Iterator $collection); + public function __invoke(); } diff --git a/src/Contract/Transformation/Runable.php b/src/Contract/Transformation/Runable.php index dff0e8e32..d70349234 100644 --- a/src/Contract/Transformation/Runable.php +++ b/src/Contract/Transformation/Runable.php @@ -4,8 +4,6 @@ namespace loophp\collection\Contract\Transformation; -use loophp\collection\Contract\Operation; - /** * @psalm-template TKey * @psalm-template TKey of array-key @@ -16,5 +14,5 @@ interface Runable /** * @psalm-return \loophp\collection\Contract\Collection */ - public function run(Operation ...$operations); + public function run(callable ...$operations); } diff --git a/src/Contract/Transformation/Transformable.php b/src/Contract/Transformation/Transformable.php index 0a70fb783..465631051 100644 --- a/src/Contract/Transformation/Transformable.php +++ b/src/Contract/Transformation/Transformable.php @@ -4,8 +4,6 @@ namespace loophp\collection\Contract\Transformation; -use loophp\collection\Contract\Transformation; - /** * @psalm-template TKey * @psalm-template TKey of array-key @@ -13,11 +11,5 @@ */ interface Transformable { - /** - * @param \loophp\collection\Contract\Transformation ...$transformers - * @psalm-param \loophp\collection\Contract\Transformation ...$transformers - * - * @return \loophp\collection\Iterator\ClosureIterator|mixed - */ - public function transform(Transformation ...$transformers); + public function transform(callable ...$transformers); } diff --git a/src/Operation/Append.php b/src/Operation/Append.php index 9a992dd4d..2720df8aa 100644 --- a/src/Operation/Append.php +++ b/src/Operation/Append.php @@ -16,25 +16,10 @@ */ final class Append extends AbstractOperation implements Operation { - /** - * @param mixed ...$items - * @psalm-param T ...$items - */ - public function __construct(...$items) - { - $this->storage['items'] = $items; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param list $items - * - * @psalm-return Generator - */ - static function (Iterator $iterator, array $items): Generator { + return static function (...$items): Closure { + return static function (Iterator $iterator) use ($items): Generator { foreach ($iterator as $key => $value) { yield $key => $value; } @@ -43,5 +28,6 @@ static function (Iterator $iterator, array $items): Generator { yield $key => $item; } }; + }; } } diff --git a/src/Operation/Apply.php b/src/Operation/Apply.php index 88d40d3a8..2271f98b0 100644 --- a/src/Operation/Apply.php +++ b/src/Operation/Apply.php @@ -16,15 +16,6 @@ */ final class Apply extends AbstractOperation implements Operation { - /** - * @param callable ...$callbacks - * @psalm-param callable(T, TKey):(bool) ...$callbacks - */ - public function __construct(callable ...$callbacks) - { - $this->storage['callbacks'] = $callbacks; - } - /** * @psalm-return Closure(Iterator, list):(Generator) */ @@ -32,21 +23,26 @@ public function __invoke(): Closure { return /** - * @psalm-param Iterator $iterator * @psalm-param list $callbacks */ - static function (Iterator $iterator, array $callbacks): Generator { - foreach ($iterator as $key => $value) { - foreach ($callbacks as $callback) { - if (true === $callback($value, $key)) { - continue; - } + static function (callable ...$callbacks): Closure { + return + /** + * @psalm-param \Iterator $iterator + */ + static function (Iterator $iterator) use ($callbacks): Generator { + foreach ($iterator as $key => $value) { + foreach ($callbacks as $callback) { + if (true === $callback($value, $key)) { + continue; + } - break; - } + break; + } - yield $key => $value; - } + yield $key => $value; + } + }; }; } } diff --git a/src/Operation/Associate.php b/src/Operation/Associate.php index 349552bbf..d8cc002f3 100644 --- a/src/Operation/Associate.php +++ b/src/Operation/Associate.php @@ -16,22 +16,6 @@ */ final class Associate extends AbstractOperation implements Operation { - /** - * @psalm-param null|callable(TKey, T):(TKey) $callbackForKeys - * @psalm-param null|callable(TKey, T):(T) $callbackForValues - */ - public function __construct(?callable $callbackForKeys = null, ?callable $callbackForValues = null) - { - $this->storage = [ - 'callbackForKeys' => $callbackForKeys ?? static function ($key, $value) { - return $key; - }, - 'callbackForValues' => $callbackForValues ?? static function ($key, $value) { - return $value; - }, - ]; - } - /** * @psalm-return Closure(Iterator, callable(TKey, T):(TKey), callable(TKey, T):(T)):(Generator) */ @@ -39,14 +23,32 @@ public function __invoke(): Closure { return /** - * @psalm-param Iterator $iterator * @psalm-param callable(TKey, T):(TKey) $callbackForKeys - * @psalm-param callable(TKey, T):(T) $callbackForValues */ - static function (Iterator $iterator, callable $callbackForKeys, callable $callbackForValues): Generator { - foreach ($iterator as $key => $value) { - yield $callbackForKeys($key, $value) => $callbackForValues($key, $value); - } + static function (?callable $callbackForKeys = null): Closure { + $callbackForKeys = $callbackForKeys ?? static function ($key, $value) { + return $key; + }; + + return + /** + * @psalm-param callable(TKey, T):(T) $callbackForValues + */ + static function (?callable $callbackForValues = null) use ($callbackForKeys): Closure { + $callbackForValues = $callbackForValues ?? static function ($key, $value) { + return $value; + }; + + return + /** + * @psalm-param \Iterator $iterator + */ + static function (Iterator $iterator) use ($callbackForKeys, $callbackForValues): Generator { + foreach ($iterator as $key => $value) { + yield $callbackForKeys($key, $value) => $callbackForValues($key, $value); + } + }; + }; }; } } diff --git a/src/Operation/Cache.php b/src/Operation/Cache.php index 43c6a1c69..4654ba56a 100644 --- a/src/Operation/Cache.php +++ b/src/Operation/Cache.php @@ -18,21 +18,18 @@ */ final class Cache extends AbstractOperation implements Operation { - public function __construct(CacheItemPoolInterface $cache) - { - $this->storage['cache'] = $cache; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * - * @psalm-return Generator - */ - static function (Iterator $iterator, CacheItemPoolInterface $cache): Generator { - return yield from new CacheIterator($iterator, $cache); - }; + return static function (CacheItemPoolInterface $cache): Closure { + return + /** + * @psalm-param Iterator $iterator + * + * @psalm-return Generator + */ + static function (Iterator $iterator) use ($cache): Generator { + return yield from new CacheIterator($iterator, $cache); + }; + }; } } diff --git a/src/Operation/Chunk.php b/src/Operation/Chunk.php index 7e7983574..d18385284 100644 --- a/src/Operation/Chunk.php +++ b/src/Operation/Chunk.php @@ -20,47 +20,47 @@ */ final class Chunk extends AbstractOperation implements Operation { - public function __construct(int ...$sizes) - { - $this->storage['sizes'] = new ArrayIterator($sizes); - } - /** - * @psalm-return Closure(Iterator, list):(Generator>) + * @psalm-return Closure(int...): Closure(Iterator): Generator> */ public function __invoke(): Closure { return /** - * @psalm-param Iterator $iterator - * @psalm-param ArrayIterator $sizes - * - * @psalm-return Generator> + * @psalm-param int ...$sizes */ - static function (Iterator $iterator, ArrayIterator $sizes): Generator { - $sizesIterator = (new Run(new Loop()))($sizes); + static function (int ...$sizes): Closure { + return + /** + * @psalm-param Iterator $iterator + * + * @psalm-return Generator> + */ + static function (Iterator $iterator) use ($sizes): Generator { + $sizesIterator = (new Run())()((new Loop())())(new ArrayIterator($sizes)); - $values = []; + $values = []; - foreach ($iterator as $value) { - if (0 >= $sizesIterator->current()) { - return yield from []; - } + foreach ($iterator as $value) { + if (0 >= $sizesIterator->current()) { + return yield from []; + } - if (count($values) !== $sizesIterator->current()) { - $values[] = $value; + if (count($values) !== $sizesIterator->current()) { + $values[] = $value; - continue; - } + continue; + } - $sizesIterator->next(); + $sizesIterator->next(); - yield $values; + yield $values; - $values = [$value]; - } + $values = [$value]; + } - return yield $values; + return yield $values; + }; }; } } diff --git a/src/Operation/Column.php b/src/Operation/Column.php index 5b1df8481..5cc5e4251 100644 --- a/src/Operation/Column.php +++ b/src/Operation/Column.php @@ -17,39 +17,23 @@ */ final class Column extends AbstractOperation implements Operation { - /** - * @param int|string $column - * @psalm-param array-key $column - */ - public function __construct($column) - { - $this->storage['column'] = $column; - } - /** * @psalm-return Closure(Iterator, array-key):(Generator>) */ public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param array-key $column - * - * @psalm-return Generator> - * - * @param mixed $column - */ - static function (Iterator $iterator, $column): Generator { + return static function ($column): Closure { + return static function (Iterator $iterator) use ($column): Generator { /** * @psalm-var array-key $key * @psalm-var iterable $value */ - foreach ((new Run(new Transpose()))($iterator) as $key => $value) { + foreach ((new Run())()((new Transpose())())($iterator) as $key => $value) { if ($key === $column) { return yield from $value; } } }; + }; } } diff --git a/src/Operation/Combinate.php b/src/Operation/Combinate.php index 662c14c5f..d6ed9545c 100644 --- a/src/Operation/Combinate.php +++ b/src/Operation/Combinate.php @@ -19,26 +19,26 @@ */ final class Combinate extends AbstractOperation implements Operation { - public function __construct(?int $length = null) - { - $this->storage = [ - 'length' => $length, - 'getCombinations' => function (array $dataset, int $length): Generator { - return $this->getCombinations($dataset, $length); - }, - ]; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param callable(array, int): (array) $getCombinations - * - * @psalm-return Generator> - */ - static function (Iterator $iterator, ?int $length, callable $getCombinations): Generator { + return static function (?int $length): Closure { + $getCombinations = static function (array $dataset, int $length) use (&$getCombinations): Generator { + for ($i = 0; count($dataset) - $length >= $i; ++$i) { + if (1 === $length) { + yield [$dataset[$i]]; + + continue; + } + + foreach ($getCombinations(array_slice($dataset, $i + 1), $length - 1) as $permutation) { + array_unshift($permutation, $dataset[$i]); + + yield $permutation; + } + } + }; + + return static function (Iterator $iterator) use ($length, $getCombinations): Generator { $dataset = iterator_to_array($iterator); if (0 < $length) { @@ -55,29 +55,6 @@ static function (Iterator $iterator, ?int $length, callable $getCombinations): G yield from $getCombinations($dataset, $i); } }; - } - - /** - * @param array $dataset - * @psalm-param array $dataset - * - * @return Generator> - * @psalm-return Generator> - */ - private function getCombinations(array $dataset, int $length): Generator - { - for ($i = 0; count($dataset) - $length >= $i; ++$i) { - if (1 === $length) { - yield [$dataset[$i]]; - - continue; - } - - foreach ($this->getCombinations(array_slice($dataset, $i + 1), $length - 1) as $permutation) { - array_unshift($permutation, $dataset[$i]); - - yield $permutation; - } - } + }; } } diff --git a/src/Operation/Combine.php b/src/Operation/Combine.php index 21c9e62f9..8c1ec8f61 100644 --- a/src/Operation/Combine.php +++ b/src/Operation/Combine.php @@ -19,27 +19,12 @@ */ final class Combine extends AbstractOperation implements Operation { - /** - * Combine constructor. - * - * @param mixed ...$keys - * @psalm-param TKey ...$keys - */ - public function __construct(...$keys) - { - $this->storage['keys'] = new ArrayIterator($keys); - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param ArrayIterator $keys - * - * @psalm-return Generator - */ - static function (Iterator $iterator, ArrayIterator $keys): Generator { + return static function (...$keys): Closure { + return static function (Iterator $iterator) use ($keys): Generator { + $keys = new ArrayIterator($keys); + while ($iterator->valid() && $keys->valid()) { yield $keys->current() => $iterator->current(); @@ -51,5 +36,6 @@ static function (Iterator $iterator, ArrayIterator $keys): Generator { trigger_error('Both keys and values must have the same amount of items.', E_USER_WARNING); } }; + }; } } diff --git a/src/Operation/Compact.php b/src/Operation/Compact.php index f02a6c3b7..d8b27c559 100644 --- a/src/Operation/Compact.php +++ b/src/Operation/Compact.php @@ -19,37 +19,23 @@ */ final class Compact extends AbstractOperation implements Operation { - /** - * @param mixed ...$values - * @psalm-param T ...$values - */ - public function __construct(...$values) - { - $this->storage['values'] = [] === $values ? [null] : $values; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param list $values - * - * @psalm-return Generator - */ - static function (Iterator $iterator, array $values): Generator { - return yield from - (new Run( - new Filter( - /** - * @param mixed $item - */ - static function ($item) use ($values): bool { - return !in_array($item, $values, true); - } - ) - ) - )($iterator); + return static function (...$values): Closure { + return static function (Iterator $iterator) use ($values): Generator { + $values = [] === $values ? [null] : $values; + + $filter = (new Filter())()( + /** + * @param mixed $item + */ + static function ($item) use ($values): bool { + return !in_array($item, $values, true); + } + ); + + return yield from (new Run())()($filter)($iterator); }; + }; } } diff --git a/src/Operation/Cycle.php b/src/Operation/Cycle.php index 99d1bad71..48bf5f50c 100644 --- a/src/Operation/Cycle.php +++ b/src/Operation/Cycle.php @@ -18,20 +18,10 @@ */ final class Cycle extends AbstractOperation implements Operation { - public function __construct(int $length) - { - $this->storage['length'] = $length; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * - * @psalm-return Generator - */ - static function (Iterator $iterator, int $length): Generator { + return static function (int $length): Closure { + return static function (Iterator $iterator) use ($length): Generator { if (0 === $length) { return yield from []; } @@ -42,5 +32,6 @@ static function (Iterator $iterator, int $length): Generator { $length ); }; + }; } } diff --git a/src/Operation/Diff.php b/src/Operation/Diff.php index c1b364869..d43ab07a7 100644 --- a/src/Operation/Diff.php +++ b/src/Operation/Diff.php @@ -18,30 +18,16 @@ */ final class Diff extends AbstractOperation implements Operation { - /** - * @param mixed ...$values - * @psalm-param T ...$values - */ - public function __construct(...$values) - { - $this->storage['values'] = $values; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param list $values - * - * @psalm-return Generator - */ - static function (Iterator $iterator, array $values): Generator { + return static function (...$values): Closure { + return static function (Iterator $iterator) use ($values): Generator { foreach ($iterator as $key => $value) { if (false === in_array($value, $values, true)) { yield $key => $value; } } }; + }; } } diff --git a/src/Operation/DiffKeys.php b/src/Operation/DiffKeys.php index ea9e21bb0..a9e9cfad2 100644 --- a/src/Operation/DiffKeys.php +++ b/src/Operation/DiffKeys.php @@ -18,32 +18,16 @@ */ final class DiffKeys extends AbstractOperation implements Operation { - /** - * @param mixed ...$values - * @psalm-param TKey ...$values - */ - public function __construct(...$values) - { - $this->storage['values'] = $values; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param list $values - * - * @psalm-return Generator - * - * @param mixed $values - */ - static function (Iterator $iterator, array $values): Generator { + return static function (...$values): Closure { + return static function (Iterator $iterator) use ($values): Generator { foreach ($iterator as $key => $value) { if (false === in_array($key, $values, true)) { yield $key => $value; } } }; + }; } } diff --git a/src/Operation/Explode.php b/src/Operation/Explode.php index 7cb2f6123..ba28839bc 100644 --- a/src/Operation/Explode.php +++ b/src/Operation/Explode.php @@ -17,46 +17,32 @@ */ final class Explode extends AbstractOperation implements Operation { - /** - * @param mixed ...$explodes - * @psalm-param T ...$explodes - */ - public function __construct(...$explodes) - { - $this->storage['explodes'] = $explodes; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param list $explodes - * - * @psalm-return Generator> - */ - static function (Iterator $iterator, array $explodes): Generator { - return yield from (new Run( - new Split( - ...array_map( - /** - * @param mixed $explode - * @psalm-param T $explode - */ - static function ($explode): Closure { - return - /** - * @param mixed $value - * @psalm-param T $value - */ - static function ($value) use ($explode): bool { - return $value === $explode; - }; - }, - $explodes - ) + return static function (...$explodes): Closure { + return static function (Iterator $iterator) use ($explodes): Generator { + $split = (new Split())()( + ...array_map( + /** + * @param mixed $explode + * @psalm-param T $explode + */ + static function ($explode): Closure { + return + /** + * @param mixed $value + * @psalm-param T $value + */ + static function ($value) use ($explode): bool { + return $value === $explode; + }; + }, + $explodes ) - ))($iterator); + ); + + return yield from (new Run())()($split)($iterator); }; + }; } } diff --git a/src/Operation/Filter.php b/src/Operation/Filter.php index cef23d1f1..aae60bea4 100644 --- a/src/Operation/Filter.php +++ b/src/Operation/Filter.php @@ -17,35 +17,26 @@ */ final class Filter extends AbstractOperation implements Operation { - public function __construct(callable ...$callbacks) + public function __invoke(): Closure { - $defaultCallback = - /** - * @param mixed $value - * @param mixed $key - * @psalm-param T $value - * @psalm-param TKey $key - * @psalm-param Iterator $iterator - */ - static function ($value, $key, Iterator $iterator): bool { - return (bool) $value; - }; + return static function (callable ...$callbacks): Closure { + return static function (Iterator $iterator) use ($callbacks): Generator { + $defaultCallback = + /** + * @param mixed $value + * @param mixed $key + * @psalm-param T $value + * @psalm-param TKey $key + * @psalm-param Iterator $iterator + */ + static function ($value, $key, Iterator $iterator): bool { + return (bool) $value; + }; - $this->storage['callbacks'] = [] === $callbacks ? - [$defaultCallback] : - $callbacks; - } + $callbacks = [] === $callbacks ? + [$defaultCallback] : + $callbacks; - public function __invoke(): Closure - { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param list):(bool)> $callbacks - * - * @psalm-return Generator - */ - static function (Iterator $iterator, array $callbacks): Generator { return yield from array_reduce( $callbacks, static function (Iterator $carry, callable $callback): CallbackFilterIterator { @@ -54,5 +45,6 @@ static function (Iterator $carry, callable $callback): CallbackFilterIterator { $iterator ); }; + }; } } diff --git a/src/Operation/First.php b/src/Operation/First.php index e352feb4f..d674998a0 100644 --- a/src/Operation/First.php +++ b/src/Operation/First.php @@ -19,59 +19,37 @@ */ final class First extends AbstractOperation implements Operation { - /** - * @var callable - * @psalm-var callable(T, TKey):(bool) - */ - private $callback; - - /** - * @psalm-param callable(T, TKey):(bool)|null $callback - * - * @psalm-param T|null $default - */ - public function __construct(?callable $callback = null, int $size = 1) - { - $defaultCallback = - /** - * @param mixed $value - * @param mixed $key - * @psalm-param T $value - * @psalm-param TKey $key - * @psalm-param Iterator $iterator - */ - static function ($value, $key, Iterator $iterator): bool { - return true; - }; - - $this->storage = [ - 'callback' => $callback ?? $defaultCallback, - 'size' => $size, - ]; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * - * @psalm-return Generator - */ - static function (Iterator $iterator, callable $callback, int $size): Generator { - $callback = + return static function (?callable $callback = null): Closure { + return static function (int $size = 1) use ($callback): Closure { + return /** - * @param mixed $value - * @param mixed $key - * @psalm-param T $value - * @psalm-param TKey $key - * @psalm-param Iterator $iterator + * @psalm-param \Iterator $iterator + * + * @psalm-return \Generator */ - static function ($value, $key, Iterator $iterator) use ($callback): bool { - return true === $callback($value, $key, $iterator); + static function (Iterator $iterator) use ($callback, $size): Generator { + $defaultCallback = + /** + * @param mixed $value + * @param mixed $key + * @psalm-param T $value + * @psalm-param TKey $key + * @psalm-param Iterator $iterator + */ + static function ($value, $key, Iterator $iterator): bool { + return true; + }; + + $callback = $callback ?? $defaultCallback; + + $filter = (new Filter())()($callback); + $limit = (new Limit())()($size)(0); + + return yield from (new Run())()($filter, $limit)($iterator); }; - - return yield from (new Run(new Filter($callback), new Limit($size)))($iterator); }; + }; } } diff --git a/src/Operation/Flatten.php b/src/Operation/Flatten.php index 5b45e73b0..f0ead4ebb 100644 --- a/src/Operation/Flatten.php +++ b/src/Operation/Flatten.php @@ -18,20 +18,10 @@ */ final class Flatten extends AbstractOperation implements Operation { - public function __construct(int $depth) - { - $this->storage['depth'] = $depth; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * - * @psalm-return Generator - */ - static function (Iterator $iterator, int $depth): Generator { + return static function (int $depth): Closure { + return static function (Iterator $iterator) use ($depth): Generator { foreach ($iterator as $key => $value) { if (false === is_iterable($value)) { yield $key => $value; @@ -41,14 +31,15 @@ static function (Iterator $iterator, int $depth): Generator { yield $subKey => $subValue; } } else { - /** @psalm-var IterableIterator $iterable */ - $iterable = (new Run(new Flatten($depth - 1)))(new IterableIterator($value)); + /** @psalm-var IterableIterator $flatten */ + $flatten = (new Flatten())()($depth - 1); - foreach ($iterable as $subKey => $subValue) { + foreach ((new Run())()($flatten)(new IterableIterator($value)) as $subKey => $subValue) { yield $subKey => $subValue; } } } }; + }; } } diff --git a/src/Operation/Forget.php b/src/Operation/Forget.php index 32cd3cc9e..fad9ef16e 100644 --- a/src/Operation/Forget.php +++ b/src/Operation/Forget.php @@ -18,25 +18,10 @@ */ final class Forget extends AbstractOperation implements Operation { - /** - * @param mixed ...$keys - * @psalm-param TKey ...$keys - */ - public function __construct(...$keys) - { - $this->storage['keys'] = $keys; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param list $keys - * - * @psalm-return Generator - */ - static function (Iterator $iterator, array $keys): Generator { + return static function (...$keys): Closure { + return static function (Iterator $iterator) use ($keys): Generator { $keys = array_flip($keys); foreach ($iterator as $key => $value) { @@ -45,5 +30,6 @@ static function (Iterator $iterator, array $keys): Generator { } } }; + }; } } diff --git a/src/Operation/Group.php b/src/Operation/Group.php index b834c298d..1850973c3 100644 --- a/src/Operation/Group.php +++ b/src/Operation/Group.php @@ -18,57 +18,62 @@ */ final class Group extends AbstractOperation implements Operation { - public function __construct(?callable $callable = null) - { - $this->storage['callable'] = $callable ?? - /** - * @param mixed $key - * @psalm-param TKey $key - * - * @param mixed $value - * @psalm-param T $value - * - * @return mixed - * @psalm-return TKey - */ - static function ($value, $key) { - return $key; - }; - } - + /** + * @psalm-return Closure(null|callable(TKey, T):(TKey)): Closure(Iterator): Generator> + */ public function __invoke(): Closure { return /** - * @psalm-param Iterator $iterator - * @psalm-param callable(TKey, T):(TKey) $callable - * - * @psalm-return Generator> + * @psalm-param null|callable(TKey, T):(T|TKey) $callable */ - static function (Iterator $iterator, callable $callable): Generator { - $callback = + static function (?callable $callable = null): Closure { + return /** - * @psalm-param array> $collect + * @psalm-param Iterator $iterator * - * @param mixed $value - * @psalm-param T $value - * - * @param mixed $key - * @psalm-param TKey $key - * - * @psalm-return array> + * @psalm-return Generator> */ - static function (array $collect, $value, $key) use ($callable): array { - if (null !== $groupKey = $callable($value, $key)) { - $collect[$groupKey][] = $value; - } else { - $collect[$key] = $value; - } + static function (Iterator $iterator) use ($callable): Generator { + $callable = $callable ?? + /** + * @param mixed $key + * @psalm-param TKey $key + * + * @param mixed $value + * @psalm-param T $value + * + * @return mixed + * @psalm-return TKey + */ + static function ($value, $key) { + return $key; + }; - return $collect; - }; + $callback = + /** + * @psalm-param array> $collect + * + * @param mixed $value + * @psalm-param T $value + * + * @param mixed $key + * @psalm-param TKey $key + * + * @psalm-return array> + */ + static function (array $collect, $value, $key) use ($callable): array { + if (null !== $groupKey = $callable($value, $key)) { + $collect[$groupKey][] = $value; + } else { + $collect[$key] = $value; + } - return yield from (new Transform(new FoldLeft($callback, [])))($iterator); + return $collect; + }; + + return yield from (new Transform(new FoldLeft($callback, [])))($iterator); + }; }; } } diff --git a/src/Operation/IfThenElse.php b/src/Operation/IfThenElse.php index fbce20e58..b04ec6300 100644 --- a/src/Operation/IfThenElse.php +++ b/src/Operation/IfThenElse.php @@ -16,33 +16,43 @@ */ final class IfThenElse extends AbstractOperation implements Operation { - /** - * @psalm-param callable(T, TKey): bool $condition - * @psalm-param callable(T, TKey): (T|TKey) $then - * @psalm-param callable(T, TKey): (T|TKey) $else - */ - public function __construct(callable $condition, callable $then, callable $else) - { - $this->storage = [ - 'condition' => $condition, - 'then' => $then, - 'else' => $else, - ]; - } - // phpcs:disable /** - * @psalm-return Closure(Iterator, callable(T, TKey): bool, callable(T, TKey): (T|TKey), callable(T, TKey): (T|TKey)): Generator + * @psalm-return Closure(callable(T, TKey): bool): Closure(callable(T, TKey): (T|TKey)): Closure(callable(T, TKey): (T|TKey)): Generator */ // phpcs:enable public function __invoke(): Closure { - return static function (Iterator $iterator, callable $condition, callable $then, callable $else): Generator { - foreach ($iterator as $key => $value) { - yield $key => $condition($value, $key) ? - $then($value, $key) : - $else($value, $key); - } - }; + return + /** + * @psalm-param callable(T, TKey): bool $condition + */ + static function (callable $condition): Closure { + return + /** + * @psalm-param callable(T, TKey): (T|TKey) $then + */ + static function (callable $then) use ($condition): Closure { + return + /** + * @psalm-param callable(T, TKey): (T|TKey) $else + */ + static function (callable $else) use ($condition, $then): Closure { + return + /** + * @psalm-param Iterator $iterator + * + * @psalm-return Generator + */ + static function (Iterator $iterator) use ($condition, $then, $else): Generator { + foreach ($iterator as $key => $value) { + yield $key => $condition($value, $key) ? + $then($value, $key) : + $else($value, $key); + } + }; + }; + }; + }; } } diff --git a/src/Operation/Intersect.php b/src/Operation/Intersect.php index e64ccb3a0..abe6dcd94 100644 --- a/src/Operation/Intersect.php +++ b/src/Operation/Intersect.php @@ -18,25 +18,10 @@ */ final class Intersect extends AbstractOperation implements Operation { - /** - * @param mixed ...$values - * @psalm-param T ...$values - */ - public function __construct(...$values) - { - $this->storage['values'] = $values; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param list $values - * - * @psalm-return Generator - */ - static function (Iterator $iterator, array $values): Generator { + return static function (...$values): Closure { + return static function (Iterator $iterator) use ($values): Generator { foreach ($iterator as $key => $value) { if (false === in_array($value, $values, true)) { continue; @@ -45,5 +30,6 @@ static function (Iterator $iterator, array $values): Generator { yield $key => $value; } }; + }; } } diff --git a/src/Operation/IntersectKeys.php b/src/Operation/IntersectKeys.php index 3188fc1a9..15e3d59c2 100644 --- a/src/Operation/IntersectKeys.php +++ b/src/Operation/IntersectKeys.php @@ -18,27 +18,10 @@ */ final class IntersectKeys extends AbstractOperation implements Operation { - /** - * @param mixed ...$values - * @psalm-param TKey ...$values - */ - public function __construct(...$values) - { - $this->storage['values'] = $values; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param list $values - * - * @psalm-return Generator - * - * @param mixed $values - */ - static function (Iterator $iterator, array $values): Generator { + return static function (...$values): Closure { + return static function (Iterator $iterator) use ($values): Generator { foreach ($iterator as $key => $value) { if (false === in_array($key, $values, true)) { continue; @@ -47,5 +30,6 @@ static function (Iterator $iterator, array $values): Generator { yield $key => $value; } }; + }; } } diff --git a/src/Operation/Intersperse.php b/src/Operation/Intersperse.php index f22e92544..86a4b2c88 100644 --- a/src/Operation/Intersperse.php +++ b/src/Operation/Intersperse.php @@ -11,11 +11,6 @@ use loophp\collection\Contract\Operation; /** - * Class Intersperse. - * - * Insert a given value between each element of a collection. - * Indices are not preserved. - * * @psalm-template TKey * @psalm-template TKey of array-key * @psalm-template T @@ -23,45 +18,48 @@ final class Intersperse extends AbstractOperation implements Operation { /** - * @param mixed $element - * @psalm-param T $element + * @psalm-return Closure(T): Closure(int): Closure(int): Closure(Iterator): Generator */ - public function __construct($element, int $atEvery, int $startAt) - { - if (0 > $atEvery) { - throw new InvalidArgumentException('The second parameter must be a positive integer.'); - } - - if (0 > $startAt) { - throw new InvalidArgumentException('The third parameter must be a positive integer.'); - } - - $this->storage = [ - 'element' => $element, - 'atEvery' => $atEvery, - 'startAt' => $startAt, - ]; - } - public function __invoke(): Closure { return /** - * @psalm-param Iterator $iterator - * - * @param mixed $element * @psalm-param T $element * - * @psalm-return Generator + * @param mixed $element */ - static function (Iterator $iterator, $element, int $every, int $startAt): Generator { - foreach ($iterator as $key => $value) { - if (0 === $startAt++ % $every) { - yield $element; - } + static function ($element): Closure { + return static function (int $atEvery) use ($element): Closure { + return static function (int $startAt) use ($element, $atEvery): Closure { + return + /** + * @psalm-param Iterator $iterator + * + * @psalm-return Generator + */ + static function (Iterator $iterator) use ($element, $atEvery, $startAt): Generator { + if (0 > $atEvery) { + throw new InvalidArgumentException( + 'The second parameter must be a positive integer.' + ); + } + + if (0 > $startAt) { + throw new InvalidArgumentException( + 'The third parameter must be a positive integer.' + ); + } + + foreach ($iterator as $key => $value) { + if (0 === $startAt++ % $atEvery) { + yield $element; + } - yield $key => $value; - } + yield $key => $value; + } + }; + }; + }; }; } } diff --git a/src/Operation/Iterate.php b/src/Operation/Iterate.php index 2bdd4738a..f44709c11 100644 --- a/src/Operation/Iterate.php +++ b/src/Operation/Iterate.php @@ -16,36 +16,18 @@ */ final class Iterate extends AbstractOperation implements Operation { - /** - * @param array $parameters - * @psalm-param array $parameters - * - * @psalm-param callable(...list):(array) $callback - */ - public function __construct(callable $callback, array $parameters = []) - { - $this->storage = [ - 'callback' => $callback, - 'parameters' => $parameters, - ]; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param callable(...list):(array) $callback - * - * @param array $parameters - * @psalm-param array $parameters - */ - static function (Iterator $iterator, callable $callback, array $parameters): Generator { - while (true) { - yield current( - $parameters = (array) $callback(...array_values((array) $parameters)) - ); - } + return static function (callable $callback): Closure { + return static function (...$parameters) use ($callback): Closure { + return static function (Iterator $iterator) use ($callback, $parameters): Generator { + while (true) { + yield current( + $parameters = (array) $callback(...array_values((array) $parameters)) + ); + } + }; }; + }; } } diff --git a/src/Operation/Last.php b/src/Operation/Last.php index 4394b5573..7ee285e70 100644 --- a/src/Operation/Last.php +++ b/src/Operation/Last.php @@ -17,58 +17,38 @@ */ final class Last extends AbstractOperation implements Operation { - /** - * @var callable|Closure - * @psalm-var callable(T, TKey):(bool)|Closure(T, TKey):(bool) - */ - private $callback; - - /** - * @psalm-param Closure(T, TKey):(bool)|callable(T, TKey):(bool)|null $callback - * @psalm-param T|null $default - */ - public function __construct(?callable $callback = null, int $size = 1) - { - $defaultCallback = - /** - * @param mixed $value - * @param mixed $key - * @psalm-param T $value - * @psalm-param TKey $key - * @psalm-param Iterator $iterator - */ - static function ($value, $key, Iterator $iterator): bool { - return true; - }; - - $this->storage = [ - 'callback' => $callback ?? $defaultCallback, - 'size' => $size, - ]; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * - * @psalm-return Generator - */ - static function (Iterator $iterator, callable $callback, int $size): Generator { - $callback = + return static function (?callable $callback = null): Closure { + return static function (int $size) use ($callback): Closure { + return /** - * @param mixed $value - * @param mixed $key - * @psalm-param T $value - * @psalm-param TKey $key * @psalm-param Iterator $iterator + * + * @psalm-return Generator */ - static function ($value, $key, Iterator $iterator) use ($callback): bool { - return true === $callback($value, $key, $iterator); + static function (Iterator $iterator) use ($callback, $size): Generator { + $defaultCallback = + /** + * @param mixed $value + * @param mixed $key + * @psalm-param T $value + * @psalm-param TKey $key + * @psalm-param Iterator $iterator + */ + static function ($value, $key, Iterator $iterator): bool { + return true; + }; + + $callback = $callback ?? $defaultCallback; + + $filter = (new Filter())()($callback); + $reverse = (new Reverse())(); + $limit = (new Limit())()($size)(0); + + return yield from (new Run())()($filter, $reverse, $limit)($iterator); }; - - return yield from (new Run(new Filter($callback), new Reverse(), new Limit($size)))($iterator); }; + }; } } diff --git a/src/Operation/Limit.php b/src/Operation/Limit.php index 9c625ecf4..84f30a378 100644 --- a/src/Operation/Limit.php +++ b/src/Operation/Limit.php @@ -17,28 +17,18 @@ */ final class Limit extends AbstractOperation implements Operation { - public function __construct(int $limit, int $offset = 0) - { - $this->storage = [ - 'limit' => $limit, - 'offset' => $offset, - ]; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * - * @psalm-return Generator - */ - static function (Iterator $iterator, int $limit, int $offset): Generator { - if (0 === $limit) { - return yield from []; - } + return static function (int $limit): Closure { + return static function (int $offset = 0) use ($limit): Closure { + return static function (Iterator $iterator) use ($limit, $offset): Generator { + if (0 === $limit) { + return yield from []; + } - return yield from new LimitIterator($iterator, $offset, $limit); + return yield from new LimitIterator($iterator, $offset, $limit); + }; }; + }; } } diff --git a/src/Operation/Loop.php b/src/Operation/Loop.php index 31ce8b1b6..f7309d46c 100644 --- a/src/Operation/Loop.php +++ b/src/Operation/Loop.php @@ -19,14 +19,8 @@ final class Loop extends AbstractOperation implements Operation { public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * - * @psalm-return Generator - */ - static function (Iterator $iterator): Generator { - return yield from new InfiniteIterator($iterator); - }; + return static function (Iterator $iterator): Generator { + return yield from new InfiniteIterator($iterator); + }; } } diff --git a/src/Operation/Map.php b/src/Operation/Map.php index 9376bb3a2..7fbc94256 100644 --- a/src/Operation/Map.php +++ b/src/Operation/Map.php @@ -16,21 +16,10 @@ */ final class Map extends AbstractOperation implements Operation { - public function __construct(callable ...$callbacks) - { - $this->storage['callbacks'] = $callbacks; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param list $callbacks - * - * @psalm-return Generator - */ - static function (Iterator $iterator, array $callbacks): Generator { + return static function (callable ...$callbacks): Closure { + return static function (Iterator $iterator) use ($callbacks): Generator { foreach ($iterator as $key => $value) { $callback = /** @@ -46,5 +35,6 @@ static function ($carry, callable $callback) use ($value, $key) { yield $key => array_reduce($callbacks, $callback, $value); } }; + }; } } diff --git a/src/Operation/Merge.php b/src/Operation/Merge.php index 016bf1171..d3cea5e05 100644 --- a/src/Operation/Merge.php +++ b/src/Operation/Merge.php @@ -16,25 +16,10 @@ */ final class Merge extends AbstractOperation implements Operation { - /** - * @param iterable ...$sources - * @psalm-param Iterator ...$sources - */ - public function __construct(iterable ...$sources) - { - $this->storage['sources'] = $sources; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param list> $sources - * - * @psalm-return Generator - */ - static function (Iterator $iterator, array $sources): Generator { + return static function (...$sources): Closure { + return static function (Iterator $iterator) use ($sources): Generator { foreach ($iterator as $key => $value) { yield $key => $value; } @@ -45,5 +30,6 @@ static function (Iterator $iterator, array $sources): Generator { } } }; + }; } } diff --git a/src/Operation/Normalize.php b/src/Operation/Normalize.php index 259d48bfb..a52c4b5a5 100644 --- a/src/Operation/Normalize.php +++ b/src/Operation/Normalize.php @@ -18,16 +18,10 @@ final class Normalize extends AbstractOperation implements Operation { public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * - * @psalm-return Generator - */ - static function (Iterator $iterator): Generator { - foreach ($iterator as $value) { - yield $value; - } - }; + return static function (Iterator $iterator): Generator { + foreach ($iterator as $value) { + yield $value; + } + }; } } diff --git a/src/Operation/Nth.php b/src/Operation/Nth.php index 8de721c94..0324a3b5d 100644 --- a/src/Operation/Nth.php +++ b/src/Operation/Nth.php @@ -16,32 +16,22 @@ */ final class Nth extends AbstractOperation implements Operation { - public function __construct(int $step, int $offset) - { - $this->storage = [ - 'step' => $step, - 'offset' => $offset, - ]; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * - * @psalm-return Generator - */ - static function (Iterator $iterator, int $step, int $offset): Generator { - $position = 0; + return static function (int $step): Closure { + return static function (int $offset) use ($step): Closure { + return static function (Iterator $iterator) use ($step, $offset): Generator { + $position = 0; - foreach ($iterator as $key => $value) { - if ($position++ % $step !== $offset) { - continue; - } + foreach ($iterator as $key => $value) { + if ($position++ % $step !== $offset) { + continue; + } - yield $key => $value; - } + yield $key => $value; + } + }; }; + }; } } diff --git a/src/Operation/Only.php b/src/Operation/Only.php index d8a996b28..49b9384e2 100644 --- a/src/Operation/Only.php +++ b/src/Operation/Only.php @@ -18,27 +18,10 @@ */ final class Only extends AbstractOperation implements Operation { - /** - * @param mixed ...$keys - * @psalm-param TKey ...$keys - */ - public function __construct(...$keys) - { - $this->storage = [ - 'keys' => $keys, - ]; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param list $keys - * - * @psalm-return Generator - */ - static function (Iterator $iterator, array $keys): Generator { + return static function (...$keys): Closure { + return static function (Iterator $iterator) use ($keys): Generator { if ([] === $keys) { return yield from $iterator; } @@ -53,5 +36,6 @@ static function (Iterator $iterator, array $keys): Generator { yield $key => $value; } }; + }; } } diff --git a/src/Operation/Pad.php b/src/Operation/Pad.php index db684956b..3ef39dab7 100644 --- a/src/Operation/Pad.php +++ b/src/Operation/Pad.php @@ -16,41 +16,24 @@ */ final class Pad extends AbstractOperation implements Operation { - /** - * @param mixed $value - * @psalm-param T $value - */ - public function __construct(int $size, $value) - { - $this->storage = [ - 'size' => $size, - 'value' => $value, - ]; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param T $padValue - * - * @psalm-return Generator - * - * @param mixed $padValue - */ - static function (Iterator $iterator, int $size, $padValue): Generator { - $y = 0; + return static function (int $size): Closure { + return static function ($padValue) use ($size): Closure { + return static function (Iterator $iterator) use ($size, $padValue): Generator { + $y = 0; - foreach ($iterator as $key => $value) { - ++$y; + foreach ($iterator as $key => $value) { + ++$y; - yield $key => $value; - } + yield $key => $value; + } - while ($y++ < $size) { - yield $padValue; - } + while ($y++ < $size) { + yield $padValue; + } + }; }; + }; } } diff --git a/src/Operation/Pair.php b/src/Operation/Pair.php index 1d536d717..9eeb2969e 100644 --- a/src/Operation/Pair.php +++ b/src/Operation/Pair.php @@ -15,7 +15,7 @@ * @psalm-template TKey of array-key * @psalm-template T */ -final class Pair extends AbstractOperation implements Operation +final class Pair extends AbstractOperation extends AbstractOperation implements Operation { public function __invoke(): Closure { @@ -26,8 +26,10 @@ public function __invoke(): Closure * @psalm-return Generator */ static function (Iterator $iterator): Generator { + $chunk = (new Chunk())()(2); + /** @psalm-var list $chunk */ - foreach ((new Run(new Chunk(2)))($iterator) as $chunk) { + foreach ((new Run())()($chunk)($iterator) as $chunk) { $chunk = array_values($chunk); yield $chunk[0] => $chunk[1]; diff --git a/src/Operation/Pluck.php b/src/Operation/Pluck.php index 39f5618b0..45128acbd 100644 --- a/src/Operation/Pluck.php +++ b/src/Operation/Pluck.php @@ -16,7 +16,6 @@ use loophp\collection\Transformation\Run; use loophp\collection\Transformation\Transform; use ReflectionClass; -use ReflectionException; use function array_key_exists; use function in_array; @@ -25,79 +24,53 @@ final class Pluck extends AbstractOperation implements Operation { - /** - * Pluck constructor. - * - * @param array|string $key - * @param mixed $default - */ - public function __construct($key, $default) - { - $this->storage = [ - 'key' => $key, - 'default' => $default, - 'operation' => Closure::fromCallable([$this, 'pick']), - ]; - } - public function __invoke(): Closure { - return - /** - * @param array|string $key - * @param mixed $default - */ - static function (Iterator $iterator, $key, $default, callable $pick): Generator { - $key = true === is_scalar($key) ? explode('.', trim((string) $key, '.')) : $key; + return static function ($key): Closure { + return static function ($default) use ($key): Closure { + return static function (Iterator $iterator) use ($key, $default): Generator { + $pick = static function (Iterator $iterator, $target, array $key, $default = null) use (&$pick) { + while (null !== $segment = array_shift($key)) { + if ('*' === $segment) { + if (false === is_iterable($target)) { + return $default; + } - foreach ($iterator as $value) { - yield $pick($iterator, $value, $key, $default); - } - }; - } + $result = []; - /** - * Get an item from an array or object using "dot" notation. - * - * @param Iterator $iterator - * @param mixed $target - * @param array $key - * @param mixed $default - * - * @throws ReflectionException - * - * @return mixed - */ - private function pick(Iterator $iterator, $target, array $key, $default = null) - { - while (null !== $segment = array_shift($key)) { - if ('*' === $segment) { - if (false === is_iterable($target)) { - return $default; - } + foreach ($target as $item) { + $result[] = $pick($iterator, $item, $key); + } - $result = []; + $collapse = (new Collapse())(); - foreach ($target as $item) { - $result[] = $this->pick($iterator, $item, $key); - } + return in_array('*', $key, true) ? (new Run())()($collapse)(new ArrayIterator($result)) : $result; + } - return in_array('*', $key, true) ? (new Run((new Collapse())))(new ArrayIterator($result)) : $result; - } + if ((true === is_array($target)) && (true === array_key_exists($segment, $target))) { + $target = $target[$segment]; + } elseif (($target instanceof ArrayAccess) && (true === $target->offsetExists($segment))) { + $target = $target[$segment]; + } elseif ($target instanceof Collection) { + $get = (new Get())()($segment)($default); + $target = (new Transform())()($get)(new IterableIterator($target)); + } elseif ((true === is_object($target)) && (true === property_exists($target, $segment))) { + $target = (new ReflectionClass($target))->getProperty($segment)->getValue($target); + } else { + $target = $default; + } + } - if ((true === is_array($target)) && (true === array_key_exists($segment, $target))) { - $target = $target[$segment]; - } elseif (($target instanceof ArrayAccess) && (true === $target->offsetExists($segment))) { - $target = $target[$segment]; - } elseif ($target instanceof Collection) { - $target = (new Transform(new Get($segment, $default)))(new IterableIterator($target)); - } elseif ((true === is_object($target)) && (true === property_exists($target, $segment))) { - $target = (new ReflectionClass($target))->getProperty($segment)->getValue($target); - } else { - $target = $default; - } - } + return $target; + }; - return $target; + $key = true === is_scalar($key) ? explode('.', trim((string) $key, '.')) : $key; + + foreach ($iterator as $value) { + yield $pick($iterator, $value, $key, $default); + } + }; + }; + }; } } diff --git a/src/Operation/Prepend.php b/src/Operation/Prepend.php index 1a92729a6..ff81bcbfa 100644 --- a/src/Operation/Prepend.php +++ b/src/Operation/Prepend.php @@ -16,25 +16,10 @@ */ final class Prepend extends AbstractOperation implements Operation { - /** - * @param mixed ...$items - * @psalm-param T ...$items - */ - public function __construct(...$items) - { - $this->storage['items'] = $items; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param list $items - * - * @psalm-return Generator - */ - static function (Iterator $iterator, array $items): Generator { + return static function (...$items): Closure { + return static function (Iterator $iterator) use ($items): Generator { foreach ($items as $key => $item) { yield $key => $item; } @@ -43,5 +28,6 @@ static function (Iterator $iterator, array $items): Generator { yield $key => $value; } }; + }; } } diff --git a/src/Operation/Product.php b/src/Operation/Product.php index 518498700..e4eb970e1 100644 --- a/src/Operation/Product.php +++ b/src/Operation/Product.php @@ -19,37 +19,14 @@ */ final class Product extends AbstractOperation implements Operation { - /** - * @param iterable ...$iterables - * @psalm-param Iterator ...$iterables - */ - public function __construct(iterable ...$iterables) - { - $this->storage = [ - 'iterables' => $iterables, - 'cartesian' => - /** - * @param array $input - * @psalm-param array> $input - * - * @psalm-return Generator> - */ - function (array $input): Generator { - return $this->cartesian($input); - }, - ]; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param array> $iterables - * - * @psalm-return Generator> - */ - static function (Iterator $iterator, array $iterables, callable $cartesian): Generator { + $cartesian = function (array $input): Generator { + return $this->cartesian($input); + }; + + return static function (iterable ...$iterables) use ($cartesian): Closure { + return static function (Iterator $iterator) use ($cartesian, $iterables): Generator { $its = [$iterator]; foreach ($iterables as $iterable) { @@ -58,6 +35,7 @@ static function (Iterator $iterator, array $iterables, callable $cartesian): Gen return yield from $cartesian($its); }; + }; } /** diff --git a/src/Operation/RSample.php b/src/Operation/RSample.php index 581df41f3..255f4c6a4 100644 --- a/src/Operation/RSample.php +++ b/src/Operation/RSample.php @@ -17,27 +17,18 @@ */ final class RSample extends AbstractOperation implements Operation { - public function __construct(float $probability) - { - $this->storage['probability'] = $probability; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * - * @psalm-return Generator - */ - static function (Iterator $iterator, float $probability): Generator { - return yield from (new Run( - new Filter( - static function () use ($probability): bool { - return (mt_rand() / mt_getrandmax()) < $probability; - } - ) - ))($iterator); + return static function (float $probability): Closure { + return static function (Iterator $iterator) use ($probability): Generator { + $filter = (new Filter())()( + static function () use ($probability): bool { + return (mt_rand() / mt_getrandmax()) < $probability; + } + ); + + return yield from (new Run())()($filter)($iterator); }; + }; } } diff --git a/src/Operation/Random.php b/src/Operation/Random.php index 9e373510e..dcab5073e 100644 --- a/src/Operation/Random.php +++ b/src/Operation/Random.php @@ -17,23 +17,15 @@ */ final class Random extends AbstractOperation implements Operation { - public function __construct(int $size) - { - $this->storage = [ - 'size' => $size, - ]; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * - * @psalm-return Generator - */ - static function (Iterator $iterator, int $size): Generator { - return yield from (new Run(new Limit($size), new Shuffle()))($iterator); + return static function (int $size): Closure { + return static function (Iterator $iterator) use ($size): Generator { + $limit = (new Limit())()($size)(0); + $shuffle = (new Shuffle())(); + + return yield from (new Run())()($limit, $shuffle)($iterator); }; + }; } } diff --git a/src/Operation/Range.php b/src/Operation/Range.php index 6988ff30c..11798d9d3 100644 --- a/src/Operation/Range.php +++ b/src/Operation/Range.php @@ -13,21 +13,18 @@ final class Range extends AbstractOperation implements Operation { - public function __construct(float $start = 0.0, float $end = INF, float $step = 1.0) - { - $this->storage = [ - 'start' => $start, - 'end' => $end, - 'step' => $step, - ]; - } - public function __invoke(): Closure { - return static function (Iterator $iterator, float $start, float $end, float $step): Generator { - for ($current = $start; $current < $end; $current += $step) { - yield $current; - } + return static function (float $start = 0.0): Closure { + return static function (float $end = INF) use ($start): Closure { + return static function (float $step = 1.0) use ($start, $end): Closure { + return static function (Iterator $iterator) use ($start, $end, $step): Generator { + for ($current = $start; $current < $end; $current += $step) { + yield $current; + } + }; + }; + }; }; } } diff --git a/src/Operation/Reduction.php b/src/Operation/Reduction.php index bf6f6c51c..47dc59634 100644 --- a/src/Operation/Reduction.php +++ b/src/Operation/Reduction.php @@ -16,35 +16,16 @@ */ final class Reduction extends AbstractOperation implements Operation { - /** - * @param mixed|null $initial - * @psalm-param T|null $initial - * @psalm-param callable(T|null, T, TKey):(T|null) $callback - */ - public function __construct(callable $callback, $initial = null) - { - $this->storage = [ - 'callback' => $callback, - 'initial' => $initial, - ]; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param callable(T|null, T, TKey):(T|null) $callback - * - * @param mixed $initial - * @psalm-param T|null $initial - * - * @psalm-return Generator - */ - static function (Iterator $iterator, callable $callback, $initial): Generator { - foreach ($iterator as $key => $value) { - yield $key => ($initial = $callback($initial, $value, $key)); - } + return static function (callable $callback): Closure { + return static function ($initial = null) use ($callback): Closure { + return static function (Iterator $iterator) use ($callback, $initial): Generator { + foreach ($iterator as $key => $value) { + yield $key => ($initial = $callback($initial, $value, $key)); + } + }; }; + }; } } diff --git a/src/Operation/Reverse.php b/src/Operation/Reverse.php index d089b1dc2..c5617a1bb 100644 --- a/src/Operation/Reverse.php +++ b/src/Operation/Reverse.php @@ -27,7 +27,7 @@ public function __invoke(): Closure */ static function (Iterator $iterator): Generator { /** @psalm-var array $all */ - $all = iterator_to_array((new Run(new Pack()))($iterator)); + $all = iterator_to_array((new Run())()((new Pack())())($iterator)); for (end($all); null !== key($all); prev($all)) { $item = current($all); diff --git a/src/Operation/Scale.php b/src/Operation/Scale.php index 66fb9b996..85ad08f64 100644 --- a/src/Operation/Scale.php +++ b/src/Operation/Scale.php @@ -19,51 +19,50 @@ */ final class Scale extends AbstractOperation implements Operation { - public function __construct( - float $lowerBound, - float $upperBound, - float $wantedLowerBound = 0.0, - float $wantedUpperBound = 1.0, - float $base = 0.0 - ) { - $wantedLowerBound = (0.0 === $wantedLowerBound) ? (0.0 === $base ? 0.0 : 1.0) : $wantedLowerBound; // phpcs:ignore - $wantedUpperBound = (1.0 === $wantedUpperBound) ? (0.0 === $base ? 1.0 : $base) : $wantedUpperBound; // phpcs:ignore + public function __invoke(): Closure + { + return static function (float $lowerBound): Closure { + return static function (float $upperBound) use ($lowerBound): Closure { + return static function (float $wantedLowerBound = 0.0) use ($lowerBound, $upperBound): Closure { + return static function (float $wantedUpperBound = 1.0) use ($lowerBound, $upperBound, $wantedLowerBound): Closure { // phpcs:ignore + return static function (float $base = 0.0) use ($lowerBound, $upperBound, $wantedLowerBound, $wantedUpperBound): Closure { // phpcs:ignore + return static function (Iterator $iterator) use ($lowerBound, $upperBound, $wantedLowerBound, $wantedUpperBound, $base): Generator { // phpcs:ignore + $wantedLowerBound = (0.0 === $wantedLowerBound) ? (0.0 === $base ? 0.0 : 1.0) : $wantedLowerBound; // phpcs:ignore + $wantedUpperBound = (1.0 === $wantedUpperBound) ? (0.0 === $base ? 1.0 : $base) : $wantedUpperBound; // phpcs:ignore - $this->storage['mapper'] = new Map( - /** - * @param float|int $v - */ - static function ($v) use ($lowerBound, $upperBound, $wantedLowerBound, $wantedUpperBound, $base): float { // phpcs:ignore - $mx = 0.0 === $base ? - ($v - $lowerBound) / ($upperBound - $lowerBound) : - log($v - $lowerBound, $base) / log($upperBound - $lowerBound, $base); + $mapper = (new Map())()( + static function ($v) use ($lowerBound, $upperBound, $wantedLowerBound, $wantedUpperBound, $base): float { // phpcs:ignore + $mx = 0.0 === $base ? + ($v - $lowerBound) / ($upperBound - $lowerBound) : + log($v - $lowerBound, $base) / log($upperBound - $lowerBound, $base); - $mx = $mx === -INF ? 0 : $mx; + $mx = $mx === -INF ? 0 : $mx; - return $wantedLowerBound + $mx * ($wantedUpperBound - $wantedLowerBound); - } - ); + return $wantedLowerBound + $mx * ($wantedUpperBound - $wantedLowerBound); + } + ); - $this->storage['filter'] = new Filter( - /** - * @param float|int $item - */ - static function ($item) use ($lowerBound): bool { - return $item >= $lowerBound; - }, - /** - * @param float|int $item - */ - static function ($item) use ($upperBound): bool { - return $item <= $upperBound; - } - ); - } + $filter = (new Filter())()( + /** + * @param float|int $item + */ + static function ($item) use ($lowerBound): bool { + return $item >= $lowerBound; + }, + /** + * @param float|int $item + */ + static function ($item) use ($upperBound): bool { + return $item <= $upperBound; + } + ); - public function __invoke(): Closure - { - return static function (Iterator $iterator, Map $mapper, Filter $filter): Generator { - return yield from (new Run($filter, $mapper))($iterator); + return yield from (new Run())()($filter, $mapper)($iterator); + }; + }; + }; + }; + }; }; } } diff --git a/src/Operation/Shuffle.php b/src/Operation/Shuffle.php index 7c549ca77..95125f8d1 100644 --- a/src/Operation/Shuffle.php +++ b/src/Operation/Shuffle.php @@ -27,7 +27,7 @@ public function __invoke(): Closure */ static function (Iterator $iterator): Generator { /** @psalm-var array $data */ - $data = iterator_to_array((new Run(new Pack()))($iterator)); + $data = iterator_to_array((new Run())()((new Pack())())($iterator)); while ([] !== $data) { $randomKey = array_rand($data); diff --git a/src/Operation/Since.php b/src/Operation/Since.php index a7d0a4436..18303c754 100644 --- a/src/Operation/Since.php +++ b/src/Operation/Since.php @@ -16,25 +16,10 @@ */ final class Since extends AbstractOperation implements Operation { - /** - * @param callable ...$callbacks - * @psalm-param callable(T, TKey):(bool) ...$callbacks - */ - public function __construct(callable ...$callbacks) - { - $this->storage['callbacks'] = $callbacks; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param list $callbacks - * - * @psalm-return Generator - */ - static function (Iterator $iterator, array $callbacks): Generator { + return static function (callable ...$callbacks): Closure { + return static function (Iterator $iterator) use ($callbacks): Generator { while ($iterator->valid()) { $result = array_reduce( $callbacks, @@ -57,5 +42,6 @@ static function (bool $carry, callable $callable) use ($iterator): bool { yield $iterator->key() => $iterator->current(); } }; + }; } } diff --git a/src/Operation/Skip.php b/src/Operation/Skip.php index 6e3172a79..05e7d4dc5 100644 --- a/src/Operation/Skip.php +++ b/src/Operation/Skip.php @@ -16,21 +16,10 @@ */ final class Skip extends AbstractOperation implements Operation { - public function __construct(int ...$skip) - { - $this->storage['skip'] = $skip; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param list $skip - * - * @psalm-return Generator - */ - static function (Iterator $iterator, array $skip): Generator { + return static function (int ...$skip): Closure { + return static function (Iterator $iterator) use ($skip): Generator { $skip = array_sum($skip); foreach ($iterator as $key => $value) { @@ -41,5 +30,6 @@ static function (Iterator $iterator, array $skip): Generator { yield $key => $value; } }; + }; } } diff --git a/src/Operation/Slice.php b/src/Operation/Slice.php index f3983727a..8dfc72db9 100644 --- a/src/Operation/Slice.php +++ b/src/Operation/Slice.php @@ -17,30 +17,28 @@ */ final class Slice extends AbstractOperation implements Operation { - public function __construct(int $offset, int $length = -1) - { - $this->storage = [ - 'offset' => $offset, - 'length' => $length, - ]; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * - * @psalm-return Generator - */ - static function (Iterator $iterator, int $offset, int $length): Generator { - $skip = (new Run(new Skip($offset)))($iterator); + return static function (int $offset): Closure { + return static function (int $length = -1) use ($offset): Closure { + return + /** + * @psalm-param Iterator $iterator + * + * @psalm-return Generator + */ + static function (Iterator $iterator) use ($offset, $length): Generator { + $skip = (new Skip())()($offset); + + if (-1 === $length) { + return yield from (new Run())()($skip)($iterator); + } - if (-1 === $length) { - return yield from $skip; - } + $limit = (new Limit())()($length)(0); - return yield from (new Run(new Limit($length)))($skip); + return yield from (new Run())()($skip, $limit)($iterator); + }; }; + }; } } diff --git a/src/Operation/Sort.php b/src/Operation/Sort.php index 666600da7..d23b6bdb2 100644 --- a/src/Operation/Sort.php +++ b/src/Operation/Sort.php @@ -19,63 +19,53 @@ */ final class Sort extends AbstractOperation implements Operation { - public function __construct(int $type = Operation\Sortable::BY_VALUES, ?callable $callback = null) - { - $this->storage = [ - 'type' => $type, - 'callback' => $callback ?? Closure::fromCallable([$this, 'compare']), - ]; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param callable(T, T):(int) $callback - * - * @psalm-return Generator - */ - static function (Iterator $iterator, int $type, callable $callback): Generator { - if (Operation\Sortable::BY_VALUES !== $type && Operation\Sortable::BY_KEYS !== $type) { - throw new Exception('Invalid sort type.'); - } + return static function (int $type = Operation\Sortable::BY_VALUES): Closure { + return static function (?callable $callback = null) use ($type): Closure { + $callback = $callback ?? static function ($left, $right): int { + return $left <=> $right; + }; - $operations = Operation\Sortable::BY_VALUES === $type ? - [ - 'before' => [new Pack()], - 'after' => [new Unpack()], - ] : - [ - 'before' => [new Flip(), new Pack()], - 'after' => [new Unpack(), new Flip()], - ]; - - $callback = + return /** - * @psalm-param array{0:TKey, 1:T} $left - * @psalm-param array{0:TKey, 1:T} $right + * @psalm-param \Iterator $iterator + * @psalm-param callable(T, T):(int) $callback + * + * @psalm-return \Generator */ - static function (array $left, array $right) use ($callback): int { - return $callback($left[1], $right[1]); - }; + static function (Iterator $iterator) use ($type, $callback): Generator { + if (Operation\Sortable::BY_VALUES !== $type && Operation\Sortable::BY_KEYS !== $type) { + throw new Exception('Invalid sort type.'); + } - $arrayIterator = new ArrayIterator(iterator_to_array((new Run(...$operations['before']))($iterator))); - $arrayIterator->uasort($callback); + $operations = Operation\Sortable::BY_VALUES === $type ? + [ + 'before' => [new Pack()], + 'after' => [new Unpack()], + ] : + [ + 'before' => [new Flip(), new Pack()], + 'after' => [new Unpack(), new Flip()], + ]; - return yield from (new Run(...$operations['after']))($arrayIterator); - }; - } + $callback = + /** + * @psalm-param array{0:TKey, 1:T} $left + * @psalm-param array{0:TKey, 1:T} $right + */ + static function (array $left, array $right) use ($defaultCallback): int { + return $defaultCallback($left[1], $right[1]); + }; - /** - * @psalm-param T $left - * @psalm-param T $right - * - * @param mixed $left - * @param mixed $right - */ - private function compare($left, $right): int - { - return $left <=> $right; + $arrayIterator = new ArrayIterator(iterator_to_array((new Run())()(...$operations['before'])($iterator))); + $arrayIterator->uasort($callback); + + return yield from ( + (new Run())()(...$operations['after'])($arrayIterator) + ); + }; + }; + }; } } diff --git a/src/Operation/Split.php b/src/Operation/Split.php index 090ecd0ac..96e5a8176 100644 --- a/src/Operation/Split.php +++ b/src/Operation/Split.php @@ -16,44 +16,41 @@ */ final class Split extends AbstractOperation implements Operation { - public function __construct(callable ...$callbacks) - { - $this->storage['callbacks'] = $callbacks; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param list $callbacks - * - * @psalm-return Generator> - */ - static function (Iterator $iterator, array $callbacks): Generator { - $carry = []; - - foreach ($iterator as $key => $value) { - $callbackReturn = array_reduce( - $callbacks, - static function (bool $carry, callable $callback) use ($key, $value): bool { - return $callback($value, $key) !== $carry; - }, - false - ); - - if (true === $callbackReturn && [] !== $carry) { - yield $carry; - - $carry = []; + return static function (callable ...$callbacks): Closure { + return + /** + * @psalm-param \Iterator $iterator + * @psalm-param list $callbacks + * + * @psalm-return \Generator> + */ + static function (Iterator $iterator) use ($callbacks): Generator { + $carry = []; + + foreach ($iterator as $key => $value) { + $callbackReturn = array_reduce( + $callbacks, + static function (bool $carry, callable $callback) use ($key, $value): bool { + return $callback($value, $key) !== $carry; + }, + false + ); + + if (true === $callbackReturn && [] !== $carry) { + yield $carry; + + $carry = []; + } + + $carry[] = $value; } - $carry[] = $value; - } - - if ([] !== $carry) { - yield $carry; - } - }; + if ([] !== $carry) { + yield $carry; + } + }; + }; } } diff --git a/src/Operation/Tail.php b/src/Operation/Tail.php index db6fdade5..332dd454f 100644 --- a/src/Operation/Tail.php +++ b/src/Operation/Tail.php @@ -26,7 +26,7 @@ public function __invoke(): Closure * @psalm-return Generator */ static function (Iterator $iterator): Generator { - return yield from (new Run(new Skip(1)))($iterator); + return yield from (new Run())()((new Skip())()(1))($iterator); }; } } diff --git a/src/Operation/Times.php b/src/Operation/Times.php index c73aa14d9..bf4cd5d27 100644 --- a/src/Operation/Times.php +++ b/src/Operation/Times.php @@ -17,35 +17,24 @@ */ final class Times extends AbstractOperation implements Operation { - public function __construct(?int $number = null, ?callable $callback = null) + public function __invoke(): Closure { - $number = $number ?? 0; - - if (1 > $number) { - throw new InvalidArgumentException('Invalid parameter. $number must be greater than 1.'); - } + return static function (int $number = 0): Closure { + return static function (?callable $callback = null) use ($number): Closure { + return static function (Iterator $iterator) use ($number, $callback): Generator { + if (1 > $number) { + throw new InvalidArgumentException('Invalid parameter. $number must be greater than 1.'); + } - $this->storage = [ - 'number' => $number, - 'callback' => $callback ?? static function (int $value): int { - return $value; - }, - ]; - } + $callback = $callback ?? static function (int $value): int { + return $value; + }; - public function __invoke(): Closure - { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param callable(int):(int) $callback - * - * @psalm-return Generator - */ - static function (Iterator $iterator, ?int $number, callable $callback): Generator { - for ($current = 1; $current <= $number; ++$current) { - yield $callback($current); - } + for ($current = 1; $current <= $number; ++$current) { + yield $callback($current); + } + }; }; + }; } } diff --git a/src/Operation/Transpose.php b/src/Operation/Transpose.php index bdf770ad4..f368cde6a 100644 --- a/src/Operation/Transpose.php +++ b/src/Operation/Transpose.php @@ -20,22 +20,16 @@ final class Transpose extends AbstractOperation implements Operation { public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * - * @psalm-return Generator> - */ - static function (Iterator $iterator): Generator { - $mit = new MultipleIterator(MultipleIterator::MIT_NEED_ANY); + return static function (Iterator $iterator): Generator { + $mit = new MultipleIterator(MultipleIterator::MIT_NEED_ANY); - foreach ($iterator as $collectionItem) { - $mit->attachIterator(new IterableIterator($collectionItem)); - } + foreach ($iterator as $collectionItem) { + $mit->attachIterator(new IterableIterator($collectionItem)); + } - foreach ($mit as $key => $value) { - yield current($key) => $value; - } - }; + foreach ($mit as $key => $value) { + yield current($key) => $value; + } + }; } } diff --git a/src/Operation/Until.php b/src/Operation/Until.php index ab870fd1f..c9941dcd8 100644 --- a/src/Operation/Until.php +++ b/src/Operation/Until.php @@ -16,25 +16,10 @@ */ final class Until extends AbstractOperation implements Operation { - /** - * @param callable ...$callbacks - * @psalm-param callable(T, TKey):(bool) ...$callbacks - */ - public function __construct(callable ...$callbacks) - { - $this->storage['callbacks'] = $callbacks; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param list $callbacks - * - * @psalm-return Generator - */ - static function (Iterator $iterator, array $callbacks): Generator { + return static function (callable ...$callbacks): Closure { + return static function (Iterator $iterator) use ($callbacks): Generator { foreach ($iterator as $key => $value) { yield $key => $value; @@ -53,5 +38,6 @@ static function (bool $carry, callable $callable) use ($key, $value): bool { } } }; + }; } } diff --git a/src/Operation/Window.php b/src/Operation/Window.php index c9f130d43..6c449081b 100644 --- a/src/Operation/Window.php +++ b/src/Operation/Window.php @@ -18,30 +18,30 @@ */ final class Window extends AbstractOperation implements Operation { - public function __construct(int ...$length) - { - $this->storage['length'] = new ArrayIterator($length); - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param ArrayIterator $length - * - * @psalm-return Generator> - */ - static function (Iterator $iterator, ArrayIterator $length): Generator { - /** @psalm-var Iterator $length */ - $length = (new Run(new Loop()))($length); - - for ($i = 0; iterator_count($iterator) > $i; ++$i) { - /** @psalm-var list $window */ - yield iterator_to_array((new Run(new Slice($i, $length->current())))($iterator)); - - $length->next(); - } - }; + return static function (int ...$lengths): Closure { + return + /** + * @psalm-param Iterator $iterator + * @psalm-param ArrayIterator $length + * + * @psalm-return Generator> + */ + static function (Iterator $iterator) use ($lengths): Generator { + $loop = (new Loop())(); + + /** @psalm-var Iterator $lengths */ + $lengths = (new Run())()($loop)(new ArrayIterator($lengths)); + + for ($i = 0; iterator_count($iterator) > $i; ++$i) { + $slice = (new Slice())()($i)($lengths->current()); + + yield iterator_to_array((new Run())()($slice)($iterator)); + + $lengths->next(); + } + }; + }; } } diff --git a/src/Operation/Zip.php b/src/Operation/Zip.php index 71d510238..1ed238456 100644 --- a/src/Operation/Zip.php +++ b/src/Operation/Zip.php @@ -18,36 +18,28 @@ */ final class Zip extends AbstractOperation implements Operation { - /** - * Zip constructor. - * - * @param iterable ...$iterables - */ - public function __construct(iterable ...$iterables) - { - $this->storage['iterables'] = $iterables; - } - public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * @psalm-param list> $iterables - * - * @psalm-return Generator> - */ - static function (Iterator $iterator, array $iterables): Generator { - $mit = new MultipleIterator(MultipleIterator::MIT_NEED_ANY); - $mit->attachIterator($iterator); + return static function (iterable ...$iterables): Closure { + return + /** + * @psalm-param \Iterator $iterator + * @psalm-param list> $iterables + * + * @psalm-return \Generator> + */ + static function (Iterator $iterator) use ($iterables): Generator { + $mit = new MultipleIterator(MultipleIterator::MIT_NEED_ANY); + $mit->attachIterator($iterator); - foreach ($iterables as $iterableIterator) { - $mit->attachIterator(new IterableIterator($iterableIterator)); - } + foreach ($iterables as $iterableIterator) { + $mit->attachIterator(new IterableIterator($iterableIterator)); + } - foreach ($mit as $values) { - yield $values; - } - }; + foreach ($mit as $values) { + yield $values; + } + }; + }; } } diff --git a/src/Transformation/All.php b/src/Transformation/All.php index bac2f6844..b179e5d59 100644 --- a/src/Transformation/All.php +++ b/src/Transformation/All.php @@ -21,8 +21,10 @@ final class All implements Transformation * @phpstan-return array * @psalm-return array */ - public function __invoke(Iterator $collection): array + public function __invoke() { - return iterator_to_array($collection); + return static function (Iterator $iterator): array { + return iterator_to_array($iterator); + }; } } diff --git a/src/Transformation/Contains.php b/src/Transformation/Contains.php index 4ffb76288..2cd5214c2 100644 --- a/src/Transformation/Contains.php +++ b/src/Transformation/Contains.php @@ -5,6 +5,7 @@ namespace loophp\collection\Transformation; use ArrayIterator; +use Closure; use Iterator; use loophp\collection\Contract\Transformation; @@ -32,27 +33,24 @@ public function __construct(...$values) $this->values = new ArrayIterator($values); } - /** - * @param Iterator $collection - * - * @return bool - */ - public function __invoke(Iterator $collection) + public function __invoke() { - $values = $this->values; - - foreach ($collection as $key => $value) { - foreach ($values as $k => $v) { - if ($v === $value) { - unset($values[$k]); - } - - if (0 === $values->count()) { - return true; + return static function (...$values): Closure { + return static function (Iterator $iterator) use ($values): bool { + foreach ($iterator as $key => $value) { + foreach ($values as $k => $v) { + if ($v === $value) { + unset($values[$k]); + } + + if ([] === $values) { + return true; + } + } } - } - } - return false; + return false; + }; + }; } } diff --git a/src/Transformation/Count.php b/src/Transformation/Count.php index de48eb9bf..a89b75516 100644 --- a/src/Transformation/Count.php +++ b/src/Transformation/Count.php @@ -6,7 +6,6 @@ use Iterator; use loophp\collection\Contract\Transformation; -use loophp\collection\Iterator\IterableIterator; /** * @psalm-template TKey @@ -17,8 +16,10 @@ */ final class Count implements Transformation { - public function __invoke(Iterator $collection) + public function __invoke() { - return iterator_count(new IterableIterator($collection)); + return static function (Iterator $iterator): int { + return iterator_count($iterator); + }; } } diff --git a/src/Transformation/Falsy.php b/src/Transformation/Falsy.php index 4dfb8861b..f1f56f84d 100644 --- a/src/Transformation/Falsy.php +++ b/src/Transformation/Falsy.php @@ -16,14 +16,16 @@ */ final class Falsy implements Transformation { - public function __invoke(Iterator $collection): bool + public function __invoke() { - foreach ($collection as $key => $value) { - if (false !== (bool) $value) { - return false; + return static function (Iterator $iterator): bool { + foreach ($iterator as $key => $value) { + if (false !== (bool) $value) { + return false; + } } - } - return true; + return true; + }; } } diff --git a/src/Transformation/FoldLeft.php b/src/Transformation/FoldLeft.php index 371d9aa17..405adec14 100644 --- a/src/Transformation/FoldLeft.php +++ b/src/Transformation/FoldLeft.php @@ -4,7 +4,7 @@ namespace loophp\collection\Transformation; -use Iterator; +use Closure; use loophp\collection\Contract\Transformation; /** @@ -17,44 +17,23 @@ final class FoldLeft implements Transformation { /** - * @var callable - * @psalm-var callable(T|null, T, TKey, \Iterator):(T|null) - */ - private $callback; - - /** - * @var mixed|null - * @psalm-var T|null - */ - private $initial; - - /** - * @psalm-param callable(T|null, T, TKey, \Iterator):(T|null) $callback - * - * @param mixed|null $initial - * @psalm-param T|null $initial - */ - public function __construct(callable $callback, $initial = null) - { - $this->callback = $callback; - $this->initial = $initial; - } - - /** - * @psalm-param Iterator $collection + * @psalm-param \Iterator $collection * * @return mixed|null * @psalm-return T|null */ - public function __invoke(Iterator $collection) + public function __invoke() { - $callback = $this->callback; - $initial = $this->initial; - - foreach ($collection as $key => $value) { - $initial = $callback($initial, $value, $key, $collection); - } - - return $initial; + return static function (callable $callback): Closure { + return static function ($initial = null) use ($callback): Closure { + return static function (iterable $iterable) use ($callback, $initial) { + foreach ($iterable as $key => $value) { + $initial = $callback($initial, $value, $key, $iterable); + } + + return $initial; + }; + }; + }; } } diff --git a/src/Transformation/FoldRight.php b/src/Transformation/FoldRight.php index a3d2f41ad..6f072c0d5 100644 --- a/src/Transformation/FoldRight.php +++ b/src/Transformation/FoldRight.php @@ -4,7 +4,7 @@ namespace loophp\collection\Transformation; -use Iterator; +use Closure; use loophp\collection\Contract\Transformation; use loophp\collection\Operation\Reverse; @@ -18,40 +18,22 @@ final class FoldRight implements Transformation { /** - * @var callable - * @psalm-var callable(T|null, T|null, TKey, \Iterator):(T|null) - */ - private $callback; - - /** - * @var mixed|null - * @psalm-var T|null - */ - private $initial; - - /** - * @psalm-param callable(T|null, T|null, TKey, \Iterator):(T|null) $callback - * - * @param mixed|null $initial - * @psalm-param T|null $initial - */ - public function __construct(callable $callback, $initial = null) - { - $this->callback = $callback; - $this->initial = $initial; - } - - /** - * @psalm-param Iterator $collection + * @psalm-param \Iterator $collection * * @return mixed|null * @psalm-return T|null */ - public function __invoke(Iterator $collection) + public function __invoke() { - $callback = $this->callback; - $initial = $this->initial; - - return (new Transform(new FoldLeft($callback, $initial)))((new Run(new Reverse()))($collection)); + return static function (callable $callback): Closure { + return static function ($initial = null) use ($callback): Closure { + return static function (iterable $iterable) use ($callback, $initial) { + $foldLeft = (new FoldLeft())()($callback)($initial); + $reverse = (new Reverse())(); + + return (new Transform())()($foldLeft)((new Run())()($reverse)($iterable)); + }; + }; + }; } } diff --git a/src/Transformation/Get.php b/src/Transformation/Get.php index 131227465..8809997ce 100644 --- a/src/Transformation/Get.php +++ b/src/Transformation/Get.php @@ -4,6 +4,7 @@ namespace loophp\collection\Transformation; +use Closure; use Iterator; use loophp\collection\Contract\Transformation; @@ -16,44 +17,20 @@ */ final class Get implements Transformation { - /** - * @var mixed - * @psalm-var T - */ - private $default; - - /** - * @var int|string - */ - private $key; - - /** - * @param int|string $key - * @param mixed $default - * @psalm-param T $default - */ - public function __construct($key, $default) + public function __invoke() { - $this->key = $key; - $this->default = $default; - } - - /** - * @param Iterator $collection - * - * @return T - */ - public function __invoke(Iterator $collection) - { - $keyToGet = $this->key; - $default = $this->default; - - foreach ($collection as $key => $value) { - if ($key === $keyToGet) { - return $value; - } - } - - return $default; + return static function ($keyToGet): Closure { + return static function ($default) use ($keyToGet): Closure { + return static function (Iterator $collection) use ($keyToGet, $default) { + foreach ($collection as $key => $value) { + if ($key === $keyToGet) { + return $value; + } + } + + return $default; + }; + }; + }; } } diff --git a/src/Transformation/Has.php b/src/Transformation/Has.php index d7a5be92a..ed030438f 100644 --- a/src/Transformation/Has.php +++ b/src/Transformation/Has.php @@ -4,6 +4,7 @@ namespace loophp\collection\Transformation; +use Closure; use Iterator; use loophp\collection\Contract\Transformation; @@ -16,35 +17,18 @@ */ final class Has implements Transformation { - /** - * @var callable - * @psalm-var callable(TKey, T):(bool) - */ - private $callback; - - /** - * @psalm-param callable(TKey, T):(bool) $callback - */ - public function __construct(callable $callback) - { - $this->callback = $callback; - } - - /** - * @param Iterator $collection - * - * @return bool - */ - public function __invoke(Iterator $collection) + public function __invoke() { - $callback = $this->callback; - - foreach ($collection as $key => $value) { - if ($callback($key, $value) === $value) { - return true; - } - } - - return false; + return static function (callable $callback): Closure { + return static function (Iterator $iterator) use ($callback): bool { + foreach ($iterator as $key => $value) { + if ($callback($key, $value) === $value) { + return true; + } + } + + return false; + }; + }; } } diff --git a/src/Transformation/Implode.php b/src/Transformation/Implode.php index aedaf15c3..09e63ee09 100644 --- a/src/Transformation/Implode.php +++ b/src/Transformation/Implode.php @@ -5,6 +5,7 @@ namespace loophp\collection\Transformation; use CachingIterator; +use Closure; use Iterator; use loophp\collection\Contract\Transformation; @@ -17,38 +18,32 @@ */ final class Implode implements Transformation { - /** - * @var string - */ - private $glue; - - public function __construct(string $glue) + public function __invoke() { - $this->glue = $glue; - } - - public function __invoke(Iterator $collection): string - { - $glue = $this->glue; - - $callback = - /** - * @psalm-param TKey $key - * @psalm-param CachingIterator $iterator - * - * @param mixed $key - * @param mixed $iterator - */ - static function (string $carry, string $item, $key, CachingIterator $iterator) use ($glue): string { - $carry .= $item; - - if ($iterator->hasNext()) { - $carry .= $glue; - } - - return $carry; + return static function (string $glue): Closure { + return static function (Iterator $iterator) use ($glue): string { + $callback = + /** + * @psalm-param TKey $key + * @psalm-param \CachingIterator $iterator + * + * @param mixed $key + * @param mixed $iterator + */ + static function (string $carry, string $item, $key, CachingIterator $iterator) use ($glue): string { + $carry .= $item; + + if ($iterator->hasNext()) { + $carry .= $glue; + } + + return $carry; + }; + + $foldLeft = (new FoldLeft())()($callback)(''); + + return (string) (new Transform())()($foldLeft)(new CachingIterator($iterator)); }; - - return (string) (new Transform(new FoldLeft($callback, '')))(new CachingIterator($collection)); + }; } } diff --git a/src/Transformation/Nullsy.php b/src/Transformation/Nullsy.php index 8b6d46aa4..0df940a39 100644 --- a/src/Transformation/Nullsy.php +++ b/src/Transformation/Nullsy.php @@ -16,17 +16,16 @@ */ final class Nullsy implements Transformation { - /** - * @psalm-param Iterator $collection - */ - public function __invoke(Iterator $collection): bool + public function __invoke() { - foreach ($collection as $key => $value) { - if (null !== $value) { - return false; + return static function (Iterator $iterator): bool { + foreach ($iterator as $key => $value) { + if (null !== $value) { + return false; + } } - } - return true; + return true; + }; } } diff --git a/src/Transformation/Reduce.php b/src/Transformation/Reduce.php index b777c0369..dc1d796f2 100644 --- a/src/Transformation/Reduce.php +++ b/src/Transformation/Reduce.php @@ -4,6 +4,7 @@ namespace loophp\collection\Transformation; +use Closure; use Iterator; use loophp\collection\Contract\Transformation; @@ -17,40 +18,21 @@ final class Reduce implements Transformation { /** - * @var callable - * @psalm-var callable(T|null, T|null, TKey):(T|null) - */ - private $callback; - - /** - * @var mixed|null - * @psalm-var T|null - */ - private $initial; - - /** - * @psalm-param callable(T|null, T|null, TKey):(T|null) $callback - * - * @param mixed|null $initial - * @psalm-param T|null $initial - */ - public function __construct(callable $callback, $initial = null) - { - $this->callback = $callback; - $this->initial = $initial; - } - - /** - * @psalm-param Iterator $collection + * @psalm-param \Iterator $collection * * @return mixed|null * @psalm-return T|scalar|null|\Iterator */ - public function __invoke(Iterator $collection) + public function __invoke() { - $callback = $this->callback; - $initial = $this->initial; - - return (new Transform(new FoldLeft($callback, $initial)))($collection); + return static function (callable $callback): Closure { + return static function ($initial = null) use ($callback): Closure { + return static function (Iterator $iterator) use ($callback, $initial) { + return (new Transform())()( + (new FoldLeft())()($callback)($initial) + )($iterator); + }; + }; + }; } } diff --git a/src/Transformation/Run.php b/src/Transformation/Run.php index 43ed7682f..54ae95d78 100644 --- a/src/Transformation/Run.php +++ b/src/Transformation/Run.php @@ -4,9 +4,8 @@ namespace loophp\collection\Transformation; -use ArrayIterator; +use Closure; use Iterator; -use loophp\collection\Contract\Operation; use loophp\collection\Contract\Transformation; use loophp\collection\Iterator\ClosureIterator; @@ -19,29 +18,19 @@ */ final class Run implements Transformation { - /** - * @var ArrayIterator - */ - private $operations; - - public function __construct(Operation ...$operations) - { - $this->operations = new ArrayIterator($operations); - } - - public function __invoke(Iterator $collection): Iterator + public function __invoke(): Closure { - return ( - new FoldLeft( - static function (Iterator $collection, Operation $operation): ClosureIterator { - return new ClosureIterator( - $operation(), - $collection, - ...array_values($operation->getArguments()) - ); - }, - $collection - ) - )($this->operations); + return static function (callable ...$operations): Closure { + return static function (Iterator $iterator) use ($operations) { + return (new FoldLeft())()( + static function (Iterator $collection, callable $operation): ClosureIterator { + return new ClosureIterator( + $operation, + $collection, + ); + } + )($iterator)($operations); + }; + }; } } diff --git a/src/Transformation/Transform.php b/src/Transformation/Transform.php index e316c7d50..f9fd2af86 100644 --- a/src/Transformation/Transform.php +++ b/src/Transformation/Transform.php @@ -4,7 +4,7 @@ namespace loophp\collection\Transformation; -use ArrayIterator; +use Closure; use Iterator; use loophp\collection\Contract\Transformation; @@ -18,40 +18,21 @@ final class Transform implements Transformation { /** - * @var ArrayIterator> - */ - private $transformers; - - /** - * @param \loophp\collection\Contract\Transformation ...$transformers - */ - public function __construct(Transformation ...$transformers) - { - $this->transformers = new ArrayIterator($transformers); - } - - /** - * @psalm-param Iterator $collection + * @psalm-param \Iterator $collection * * @return mixed|null - * @psalm-return Iterator|T + * @psalm-return T|scalar|null|\Iterator */ - public function __invoke(Iterator $collection) + public function __invoke() { - return (new FoldLeft( - /** - * @psalm-param Iterator $collection - * @psalm-param Transformation $transformer - * @psalm-param TKey $key - * - * @param mixed $key - * - * @psalm-return T - */ - static function (Iterator $collection, Transformation $transformer, $key) { - return $transformer($collection); - }, - $collection - ))($this->transformers); + return static function (callable ...$transformers): Closure { + return static function (Iterator $iterator) use ($transformers) { + return (new FoldLeft())()( + static function (Iterator $collection, callable $transformer, $key) { + return $transformer($collection); + } + )($iterator)($transformers); + }; + }; } } diff --git a/src/Transformation/Truthy.php b/src/Transformation/Truthy.php index c643a27b2..00143388e 100644 --- a/src/Transformation/Truthy.php +++ b/src/Transformation/Truthy.php @@ -16,14 +16,16 @@ */ final class Truthy implements Transformation { - public function __invoke(Iterator $collection): bool + public function __invoke() { - foreach ($collection as $key => $value) { - if (false === (bool) $value) { - return false; + return static function (Iterator $iterator): bool { + foreach ($iterator as $key => $value) { + if (false === (bool) $value) { + return false; + } } - } - return true; + return true; + }; } }