Skip to content

Commit

Permalink
chore: more specific return type for chunk() method (#351)
Browse files Browse the repository at this point in the history
* chore: more specific return type for chunk() method

* chore(sa): fix psalm type infer for Chunk operation

---------

Co-authored-by: Yevhen Sidelnyk <yevhen.sidelnyk@stfalcon.com>
  • Loading branch information
rela589n and Yevhen Sidelnyk authored Dec 11, 2024
1 parent af76bb7 commit 3cfae9d
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/Contract/Operation/Chunkable.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ interface Chunkable
*
* @see https://loophp-collection.readthedocs.io/en/stable/pages/api.html#chunk
*
* @return Collection<int, list<T>>
* @return Collection<int, non-empty-list<T>>
*/
public function chunk(int ...$sizes): Collection;
}
30 changes: 14 additions & 16 deletions src/Operation/Chunk.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,47 +18,45 @@
final class Chunk extends AbstractOperation
{
/**
* @return Closure(int...): Closure(iterable<TKey, T>): Generator<int, list<T>>
* @return Closure(int...): Closure(iterable<TKey, T>): Generator<int, non-empty-list<T>>
*/
public function __invoke(): Closure
{
return
/**
* @return Closure(iterable<TKey, T>): Generator<int, list<T>>
* @return Closure(iterable<TKey, T>): Generator<int, non-empty-list<T>>
*/
static fn (int ...$sizes): Closure =>
/**
* @param iterable<TKey, T> $iterable
*
* @return Generator<int, list<T>>
* @return Generator<int, non-empty-list<T>>
*/
static function (iterable $iterable) use ($sizes): Generator {
$sizesCount = count($sizes);
$i = 0;
$values = [];
$chunkIndex = 0;
$chunk = [];

foreach ($iterable as $value) {
$size = $sizes[$i % $sizesCount];
$size = $sizes[$chunkIndex % $sizesCount];

if (0 >= $size) {
return;
}

if (count($values) !== $size) {
$values[] = $value;
$chunk[] = $value;

continue;
}

++$i;
if (count($chunk) >= $size) {
++$chunkIndex;

yield $values;
yield $chunk;

$values = [$value];
$chunk = [];
}
}

if ([] !== $values) {
yield $values;
if ([] !== $chunk) {
yield $chunk;
}
};
}
Expand Down
6 changes: 3 additions & 3 deletions tests/static-analysis/chunk.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@
use loophp\collection\Contract\Collection as CollectionInterface;

/**
* @param CollectionInterface<int, list<int>> $collection
* @param CollectionInterface<int, non-empty-list<int>> $collection
*/
function chunk_checkList(CollectionInterface $collection): void {}
/**
* @param CollectionInterface<int, list<string>> $collection
* @param CollectionInterface<int, non-empty-list<string>> $collection
*/
function chunk_checkMap(CollectionInterface $collection): void {}

chunk_checkList(Collection::fromIterable(range(0, 6))->chunk(1));
chunk_checkList(Collection::fromIterable(range(0, 6))->chunk(1, 2));

// These should work but Psalm restricts type to list<'baz'|'taz'>
// These should work but Psalm restricts type to non-empty-list<'baz'|'taz'>
/** @psalm-suppress InvalidArgument */
chunk_checkMap(Collection::fromIterable(['foo' => 'bar', 'baz' => 'taz'])->chunk(1));
/** @psalm-suppress InvalidArgument */
Expand Down

0 comments on commit 3cfae9d

Please sign in to comment.