Skip to content

Commit

Permalink
refactor: Update Every operation.
Browse files Browse the repository at this point in the history
BREAKING CHANGE: no
  • Loading branch information
drupol committed Apr 11, 2021
1 parent e183f29 commit e0cc29c
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 42 deletions.
2 changes: 1 addition & 1 deletion src/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ public static function empty(): CollectionInterface

public function every(callable ...$callbacks): CollectionInterface
{
return new self(Every::of()(...$callbacks), $this->getIterator());
return new self(Every::of()(static fn (): bool => false)(...$callbacks), $this->getIterator());
}

public function explode(...$explodes): CollectionInterface
Expand Down
98 changes: 57 additions & 41 deletions src/Operation/Every.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,64 +18,80 @@
final class Every extends AbstractOperation
{
/**
* @psalm-return Closure(callable(T, TKey, Iterator<TKey, T>): bool ...): Closure(Iterator<TKey, T>): Generator<int|TKey, bool>
* @psalm-return Closure(callable(T, TKey, Iterator<TKey, T>...): bool): Closure(callable(T, TKey, Iterator<TKey, T>...): bool): Closure(Iterator<TKey, T>): Generator<int|TKey, bool>
*/
public function __invoke(): Closure
{
return
/**
* @psalm-param callable(T, TKey, Iterator<TKey, T>): bool ...$callbacks
* @psalm-param callable(T, TKey, Iterator<TKey, T>): bool ...$matchers
*
* @psalm-return Closure(...callable(T, TKey, Iterator<TKey, T>): bool): Closure(Iterator<TKey, T>): Generator<int|TKey, bool>
*/
static function (callable ...$callbacks): Closure {
$reducerCallback =
static function (callable ...$matchers): Closure {
return
/**
* @param mixed $key
* @psalm-param TKey $key
* @psalm-param callable(T, TKey, Iterator<TKey, T>): bool ...$callbacks
*
* @psalm-return Closure(T): Closure(Iterator<TKey, T>): Closure(bool, callable(T, TKey, Iterator<TKey, T>): bool): bool
* @psalm-return Closure(Iterator<TKey, T>): Generator<int|TKey, bool>
*/
static fn ($key): Closure =>
/**
* @param mixed $current
* @psalm-param T $current
*
* @psalm-return Closure(Iterator<TKey, T>): Closure(bool, callable(T, TKey, Iterator<TKey, T>): bool): bool
*/
static fn ($current): Closure =>
static function (callable ...$callbacks) use ($matchers): Closure {
$callbackReducer =
/**
* @psalm-param Iterator<TKey, T> $iterator
* @psalm-param list<callable(T, TKey, Iterator<TKey, T>): bool> $callbacks
*
* @psalm-return Closure(bool, callable(T, TKey, Iterator<TKey, T>): bool): bool
* @psalm-return Closure(T, TKey, Iterator<TKey, T>): bool
*/
static fn (Iterator $iterator): Closure =>
static fn (array $callbacks): Closure =>
/**
* @psalm-param bool $carry
* @psalm-param callable(T, TKey, Iterator<TKey, T>): bool $callable
* @param mixed $value
* @psalm-param T $value
*
* @param mixed $key
* @psalm-param TKey $key
*
* @psalm-param Iterator<TKey, T> $iterator
*/
static fn (bool $carry, callable $callable): bool => $carry || $callable($current, $key, $iterator);
static fn ($value, $key, Iterator $iterator): bool => array_reduce(
$callbacks,
static fn (bool $carry, callable $callback): bool => $carry || $callback($value, $key, $iterator),
false
);

return
/**
* @psalm-param Iterator<TKey, T> $iterator
*
* @psalm-return Generator<int|TKey, bool>
*/
static function (Iterator $iterator) use ($callbacks, $reducerCallback): Generator {
// We could use FoldLeft but there is no need to go through all the items,
// we just need to return false as soon as the callbacks returns false.
foreach ($iterator as $key => $value) {
$result = array_reduce(
$callbacks,
$reducerCallback($key)($value)($iterator),
false
);
$mapCallback =
/**
* @psalm-param callable(T, TKey, Iterator<TKey, T>) $reducer1
*
* @psalm-return Closure(callable(T, TKey, Iterator<TKey, T>)): Closure(T, TKey, Iterator<TKey, T>): bool
*/
static fn (callable $reducer1): Closure =>
/**
* @psalm-param callable(T, TKey, Iterator<TKey, T>) $reducer2
*
* @psalm-return Closure(T, TKey, Iterator<TKey, T>): bool
*/
static fn (callable $reducer2): Closure =>
/**
* @param mixed $value
* @psalm-param T $value
*
* @param mixed $key
* @psalm-param TKey $key
*
* @psalm-param Iterator<TKey, T> $iterator
*/
static fn ($value, $key, Iterator $iterator): bool => $reducer1($value, $key, $iterator) !== $reducer2($value, $key, $iterator);

if (false === $result) {
return yield $key => false;
}
}
/** @psalm-var Closure(Iterator<TKey, T>): Generator<TKey|int, bool> $pipe */
$pipe = Pipe::of()(
Map::of()($mapCallback($callbackReducer($callbacks))($callbackReducer($matchers))),
DropWhile::of()(static fn (bool $value): bool => true === $value),
Append::of()(true),
Head::of(),
);

return yield true;
// Point free style.
return $pipe;
};
};
}
Expand Down

0 comments on commit e0cc29c

Please sign in to comment.