From 13b5d6d55751c33bdb8e2ed838d214ff0f8d42b5 Mon Sep 17 00:00:00 2001 From: Pol Dellaiera Date: Thu, 24 Sep 2020 18:13:16 +0200 Subject: [PATCH] refactor: Leverage tacit programming (point free style) Point free style operation to avoid repeating closures that are already existing in Compose operation. --- src/Operation/Flatten.php | 26 +++++++------- src/Operation/Frequency.php | 55 ++++++++++++++-------------- src/Operation/Head.php | 14 +++----- src/Operation/Intersect.php | 1 + src/Operation/Pack.php | 20 +++++------ src/Operation/Since.php | 72 +++++++++++++++++++------------------ src/Operation/Unwrap.php | 8 ++--- src/Operation/Unzip.php | 30 +++++++++------- src/Operation/Wrap.php | 18 ++++------ 9 files changed, 120 insertions(+), 124 deletions(-) diff --git a/src/Operation/Flatten.php b/src/Operation/Flatten.php index 4bd53cc31..003420a2b 100644 --- a/src/Operation/Flatten.php +++ b/src/Operation/Flatten.php @@ -36,23 +36,21 @@ static function (Iterator $iterator) use ($depth): Generator { foreach ($iterator as $key => $value) { if (false === is_iterable($value)) { yield $key => $value; - } elseif (1 === $depth) { - /** @psalm-var TKey $subKey */ - /** @psalm-var T $subValue */ - foreach ($value as $subKey => $subValue) { - yield $subKey => $subValue; - } - } else { + + continue; + } + + if (1 !== $depth) { /** @psalm-var callable(Iterator): Generator $flatten */ $flatten = Flatten::of()($depth - 1); - /** - * @psalm-var TKey $subKey - * @psalm-var T $subValue - */ - foreach ($flatten(new IterableIterator($value)) as $subKey => $subValue) { - yield $subKey => $subValue; - } + $value = $flatten(new IterableIterator($value)); + } + + /** @psalm-var TKey $subKey */ + /** @psalm-var T $subValue */ + foreach ($value as $subKey => $subValue) { + yield $subKey => $subValue; } } }; diff --git a/src/Operation/Frequency.php b/src/Operation/Frequency.php index cf2c93d6f..3e7d7ff78 100644 --- a/src/Operation/Frequency.php +++ b/src/Operation/Frequency.php @@ -20,42 +20,45 @@ final class Frequency extends AbstractOperation */ public function __invoke(): Closure { - return + $reduceCallback = /** - * @psalm-param Iterator $iterator + * @psalm-param array $storage + * @psalm-param T $value * - * @psalm-return Generator + * @psalm-return array + * + * @param mixed $value */ - static function (Iterator $iterator): Generator { - $storage = []; - - foreach ($iterator as $value) { - $added = false; - - foreach ($storage as $key => $data) { - if ($data['value'] !== $value) { - continue; - } - - ++$storage[$key]['count']; - $added = true; - - break; - } + static function (array $storage, $value): array { + $added = false; - if (false !== $added) { + foreach ($storage as $key => $data) { + if ($data[1] !== $value) { continue; } - $storage[] = [ - 'value' => $value, - 'count' => 1, - ]; + ++$storage[$key][0]; + $added = true; + + break; } - foreach ($storage as $value) { - yield $value['count'] => $value['value']; + if (false !== $added) { + return $storage; } + + $storage[] = [1, $value]; + + return $storage; }; + + /** @psalm-var Closure(Iterator): Generator $compose */ + $compose = Compose::of()( + FoldLeft::of()($reduceCallback)([]), + Flatten::of()(1), + Unpack::of() + ); + + return $compose; } } diff --git a/src/Operation/Head.php b/src/Operation/Head.php index 08af79383..e8ad4405d 100644 --- a/src/Operation/Head.php +++ b/src/Operation/Head.php @@ -20,14 +20,10 @@ final class Head extends AbstractOperation */ public function __invoke(): Closure { - return - /** - * @psalm-param Iterator $iterator - * - * @psalm-return Generator - */ - static function (Iterator $iterator): Generator { - return yield $iterator->key() => $iterator->current(); - }; + /** @psalm-var Closure(Iterator): Generator $first */ + $first = First::of(); + + // Point free style. + return $first; } } diff --git a/src/Operation/Intersect.php b/src/Operation/Intersect.php index 33050111e..9b7e6686b 100644 --- a/src/Operation/Intersect.php +++ b/src/Operation/Intersect.php @@ -47,6 +47,7 @@ static function ($value, $key, Iterator $iterator) use ($values): bool { /** @psalm-var Closure(Iterator): Generator $filter */ $filter = Filter::of()($filterCallbackFactory($values)); + // Point free style. return $filter; }; } diff --git a/src/Operation/Pack.php b/src/Operation/Pack.php index e20b6f4fb..0dfdda54b 100644 --- a/src/Operation/Pack.php +++ b/src/Operation/Pack.php @@ -16,31 +16,27 @@ final class Pack extends AbstractOperation { /** - * @psalm-return Closure(Iterator): Generator + * @psalm-return Closure(Iterator): Generator */ public function __invoke(): Closure { - $callbackForKeys = static function (): void { - }; - $callbackForValues = + $mapCallback = /** - * @psalm-param T $initial - * @psalm-param TKey $key * @psalm-param T $value + * @psalm-param TKey $key * - * @psalm-return array{0: TKey, 1: T} - * - * @param mixed $initial - * @param mixed $key * @param mixed $value + * @param mixed $key + * + * @psalm-return array{0: TKey, 1: T} */ - static function ($initial, $key, $value): array { + static function ($value, $key): array { return [$key, $value]; }; /** @psalm-var Closure(Iterator): Generator $compose */ $compose = Compose::of()( - Associate::of()($callbackForKeys)($callbackForValues), + Map::of()($mapCallback), Normalize::of() ); diff --git a/src/Operation/Since.php b/src/Operation/Since.php index 06107920f..2639a6f9e 100644 --- a/src/Operation/Since.php +++ b/src/Operation/Since.php @@ -12,6 +12,8 @@ * @psalm-template TKey * @psalm-template TKey of array-key * @psalm-template T + * + * phpcs:disable Generic.WhiteSpace.ScopeIndent.IncorrectExact */ final class Since extends AbstractOperation { @@ -28,45 +30,45 @@ public function __invoke(): Closure */ static function (callable ...$callbacks): Closure { return - /** - * @psalm-param Iterator $iterator - * - * @psalm-return Generator - */ - static function (Iterator $iterator) use ($callbacks): Generator { - $reducer = - /** - * @psalm-param Iterator $iterator - * - * @psalm-return Closure(bool, callable(T, TKey): bool): bool - */ - static function (Iterator $iterator): Closure { - return - /** - * @psalm-param bool $carry - * @psalm-param callable(T, TKey): bool $callback - */ - static function (bool $carry, callable $callback) use ($iterator): bool { - return ($callback($iterator->current(), $iterator->key())) ? - $carry : - false; - }; - }; + /** + * @psalm-param Iterator $iterator + * + * @psalm-return Generator + */ + static function (Iterator $iterator) use ($callbacks): Generator { + $reducer = + /** + * @psalm-param Iterator $iterator + * + * @psalm-return Closure(bool, callable(T, TKey): bool): bool + */ + static function (Iterator $iterator): Closure { + return + /** + * @psalm-param bool $carry + * @psalm-param callable(T, TKey): bool $callback + */ + static function (bool $carry, callable $callback) use ($iterator): bool { + return ($callback($iterator->current(), $iterator->key())) ? + $carry : + false; + }; + }; - while ($iterator->valid()) { - $result = array_reduce($callbacks, $reducer($iterator), true); + while ($iterator->valid()) { + $result = array_reduce($callbacks, $reducer($iterator), true); - if (false !== $result) { - break; - } + if (false !== $result) { + break; + } - $iterator->next(); - } + $iterator->next(); + } - for (; $iterator->valid(); $iterator->next()) { - yield $iterator->key() => $iterator->current(); - } - }; + for (; $iterator->valid(); $iterator->next()) { + yield $iterator->key() => $iterator->current(); + } + }; }; } } diff --git a/src/Operation/Unwrap.php b/src/Operation/Unwrap.php index a2e74d908..ca2462c65 100644 --- a/src/Operation/Unwrap.php +++ b/src/Operation/Unwrap.php @@ -20,12 +20,10 @@ final class Unwrap extends AbstractOperation */ public function __invoke(): Closure { - /** @psalm-var Closure(Iterator>): Generator $compose */ - $compose = Compose::of()( - Flatten::of()(1) - ); + /** @psalm-var Closure(Iterator>): Generator $flatten */ + $flatten = Flatten::of()(1); // Point free style. - return $compose; + return $flatten; } } diff --git a/src/Operation/Unzip.php b/src/Operation/Unzip.php index 5d471e857..fa5ccd2a9 100644 --- a/src/Operation/Unzip.php +++ b/src/Operation/Unzip.php @@ -12,6 +12,8 @@ * @psalm-template TKey * @psalm-template TKey of array-key * @psalm-template T + * + * phpcs:disable Generic.WhiteSpace.ScopeIndent.IncorrectExact */ final class Unzip extends AbstractOperation { @@ -20,25 +22,29 @@ final class Unzip extends AbstractOperation */ public function __invoke(): Closure { - return + $reduceCallback = /** - * @psalm-param Iterator> $iterator + * @psalm-param array> $carry + * @psalm-param iterable $value * - * @psalm-return Generator> + * @psalm-return array> */ - static function (Iterator $iterator): Generator { + static function (array $carry, iterable $value): array { $index = 0; - $result = []; - foreach ($iterator as $current) { - foreach ($current as $c) { - $result[$index++][] = $c; - } - - $index = 0; + foreach ($value as $v) { + $carry[$index++][] = $v; } - return yield from $result; + return $carry; }; + + /** @psalm-var Closure(Iterator>): Generator> $compose */ + $compose = Compose::of()( + FoldLeft::of()($reduceCallback)([]), + Unwrap::of() + ); + + return $compose; } } diff --git a/src/Operation/Wrap.php b/src/Operation/Wrap.php index 017ebbabc..5d882240b 100644 --- a/src/Operation/Wrap.php +++ b/src/Operation/Wrap.php @@ -20,27 +20,23 @@ final class Wrap extends AbstractOperation */ public function __invoke(): Closure { - $callbackForKeys = static function (): void { - }; - $callbackForValues = + $mapCallback = /** - * @psalm-param T $initial - * @psalm-param TKey $key * @psalm-param T $value + * @psalm-param TKey $key * - * @psalm-return array - * - * @param mixed $initial - * @param mixed $key * @param mixed $value + * @param mixed $key + * + * @psalm-return array */ - static function ($initial, $key, $value): array { + static function ($value, $key): array { return [$key => $value]; }; /** @psalm-var Closure(Iterator): Generator> $compose */ $compose = Compose::of()( - Associate::of()($callbackForKeys)($callbackForValues), + Map::of()($mapCallback), Normalize::of() );