Skip to content

Commit

Permalink
Make OrderedEnumerable key extend 0|positive-int
Browse files Browse the repository at this point in the history
  • Loading branch information
ricardoboss committed Jan 6, 2022
1 parent a806b9c commit 88bb2bb
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 30 deletions.
8 changes: 4 additions & 4 deletions modules/PIE/src/GenericEnumerable.php
Original file line number Diff line number Diff line change
Expand Up @@ -258,22 +258,22 @@ public function max(callable $selector): int|float|string;
public function min(callable $selector): int|float|string;

/**
* @template TKey
* @template TKey of NonNegativeInteger
*
* @param callable(TSource, TIteratorKey): TKey $keySelector
* @param null|callable(TKey, TKey): int $comparer
*
* @return GenericOrderedEnumerable<TSource>
* @return GenericOrderedEnumerable<TKey, TSource>
*/
public function orderBy(callable $keySelector, ?callable $comparer = null): GenericOrderedEnumerable;

/**
* @template TKey
* @template TKey of NonNegativeInteger
*
* @param callable(TSource, TIteratorKey): TKey $keySelector
* @param null|callable(TKey, TKey): int $comparer
*
* @return GenericOrderedEnumerable<TSource>
* @return GenericOrderedEnumerable<TKey, TSource>
*/
public function orderByDescending(callable $keySelector, ?callable $comparer = null): GenericOrderedEnumerable;

Expand Down
11 changes: 4 additions & 7 deletions modules/PIE/src/GenericOrderedEnumerable.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,26 @@
/**
* @psalm-type NonNegativeInteger = 0|positive-int
*
* @template TKey of NonNegativeInteger
* @template TSource
*
* @extends GenericEnumerable<NonNegativeInteger, TSource>
* @extends GenericEnumerable<TKey, TSource>
*/
interface GenericOrderedEnumerable extends GenericEnumerable
{
/**
* @template TKey
*
* @param callable(TSource): TKey $keySelector
* @param null|callable(TKey, TKey): int $comparer $comparer
*
* @return GenericOrderedEnumerable<TSource>
* @return GenericOrderedEnumerable<TKey, TSource>
*/
public function thenBy(callable $keySelector, ?callable $comparer = null): GenericOrderedEnumerable;

/**
* @template TKey
*
* @param callable(TSource): TKey $keySelector
* @param null|callable(TKey, TKey): int $comparer $comparer
*
* @return GenericOrderedEnumerable<TSource>
* @return GenericOrderedEnumerable<TKey, TSource>
*/
public function thenByDescending(callable $keySelector, ?callable $comparer = null): GenericOrderedEnumerable;
}
45 changes: 28 additions & 17 deletions modules/PIE/src/IsEnumerable.php
Original file line number Diff line number Diff line change
Expand Up @@ -510,12 +510,12 @@ public function min(callable $selector): int|float|string
}

/**
* @template TKey
* @template TKey of NonNegativeInteger
*
* @param callable(TSource, TIteratorKey): TKey $keySelector
* @param null|callable(TKey, TKey): int $comparer
*
* @return GenericOrderedEnumerable<TSource>
* @return GenericOrderedEnumerable<TKey, TSource>
*/
public function orderBy(callable $keySelector, ?callable $comparer = null): GenericOrderedEnumerable
{
Expand Down Expand Up @@ -544,21 +544,21 @@ public function orderBy(callable $keySelector, ?callable $comparer = null): Gene
}

/**
* @template TKey
* @template TKey of NonNegativeInteger
*
* @param callable(TSource, TIteratorKey): TKey $keySelector
* @param null|callable(TKey, TKey): int $comparer
*
* @return GenericOrderedEnumerable<TSource>
* @return GenericOrderedEnumerable<TKey, TSource>
*/
public function orderByDescending(callable $keySelector, ?callable $comparer = null): GenericOrderedEnumerable
{
$comparer ??= DefaultEqualityComparer::compare(...);

/** @var callable(TKey, TKey): int $comparer */
$invertedComparer = DefaultEqualityComparer::invert($comparer);

$invertedComparer = DefaultEqualityComparer::invert($comparer);
/** @var callable(TKey, TKey): int $invertedComparer */

return $this->orderBy($keySelector, $invertedComparer);
}

Expand Down Expand Up @@ -593,7 +593,8 @@ public function select(callable $selector): GenericEnumerable
*/
public function selectMany(callable $collectionSelector, ?callable $resultSelector = null): GenericEnumerable
{
$resultSelector ??= static fn ($element, $collectionElement, $elementKey, $collectionElementKey) => $collectionElement;
$resultSelector ??= static fn ($element, $collectionElement, $elementKey, $collectionElementKey): mixed => $collectionElement;
/** @var callable(TSource, TCollection, TIteratorKey, TCollectionKey): TResult $resultSelector */

return new Enumerable(function () use ($collectionSelector, $resultSelector) {
foreach ($this->getIterator() as $elementKey => $element) {
Expand All @@ -607,10 +608,12 @@ public function selectMany(callable $collectionSelector, ?callable $resultSelect
public function sequenceEqual(GenericEnumerable $other, ?callable $comparer = null): bool
{
$comparer ??= DefaultEqualityComparer::same(...);
/** @var callable(TSource, TSource, TIteratorKey, TIteratorKey): bool $comparer */

$mit = new MultipleIterator(MultipleIterator::MIT_KEYS_NUMERIC | MultipleIterator::MIT_NEED_ANY);
$mit->attachIterator($this->getIterator());
$mit->attachIterator($other->getIterator());
/** @var MultipleIterator<array{TSource, TSource}, array{TIteratorKey, TIteratorKey}> $mit */

foreach ($mit as $keys => $values) {
if (!$comparer($values[0], $values[1], $keys[0], $keys[1])) {
Expand Down Expand Up @@ -689,7 +692,8 @@ public function skipWhile(callable $predicate): GenericEnumerable
{
$iterator = $this->getIterator();

$whileIterator = new WhileIterator($iterator, $predicate);
/** @noinspection PhpClosureCanBeConvertedToFirstClassCallableInspection Until psalm supports first class callables: vimeo/psalm#7196 */
$whileIterator = new WhileIterator($iterator, Closure::fromCallable($predicate));
$whileIterator->rewind();
while ($whileIterator->valid()) {
$whileIterator->next();
Expand Down Expand Up @@ -739,7 +743,8 @@ public function takeLast(int $count): GenericEnumerable

public function takeWhile(callable $predicate): GenericEnumerable
{
return new Enumerable(new WhileIterator($this->getIterator(), $predicate));
/** @noinspection PhpClosureCanBeConvertedToFirstClassCallableInspection Until psalm supports first class callables: vimeo/psalm#7196 */
return new Enumerable(new WhileIterator($this->getIterator(), Closure::fromCallable($predicate)));
}

/**
Expand All @@ -765,8 +770,6 @@ public function toArray(): array
$key = $elementKey;
} else if (is_array($elementKey)) {
throw new UnexpectedValueException('Cannot use array as array key');
} else if (is_resource($elementKey)) {
throw new UnexpectedValueException('Cannot use resource as array key');
} else {
$key = (string)$elementKey;
}
Expand Down Expand Up @@ -824,6 +827,7 @@ public function unionBy(GenericEnumerable $other, callable $keySelector, ?callab

public function where(callable $predicate): GenericEnumerable
{
/** @psalm-suppress MixedArgumentTypeCoercion */
return new Enumerable(new CallbackFilterIterator($this->getIterator(), $predicate));
}

Expand All @@ -842,23 +846,30 @@ public function where(callable $predicate): GenericEnumerable
public function zip(GenericEnumerable $other, ?callable $resultSelector = null, ?callable $keySelector = null): GenericEnumerable
{
$resultSelector ??= static fn (mixed $a, mixed $b): array => [$a, $b];
/** @var callable(TSource, TOther): TResult $resultSelector */

/** @psalm-suppress UnusedClosureParam */
$keySelector ??= static fn (mixed $a, mixed $b): mixed => $a;
/** @var callable(TIteratorKey, TOtherIteratorKey): TResultKey $keySelector */

/** @var MultipleIterator<array{TIteratorKey, TOtherIteratorKey}, array{TSource, TOther}> $mit */
$mit = new MultipleIterator(MultipleIterator::MIT_KEYS_NUMERIC | MultipleIterator::MIT_NEED_ALL);
$mit->attachIterator($this->getIterator());
$mit->attachIterator($other->getIterator());
/** @var MultipleIterator<array{TIteratorKey, TOtherIteratorKey}, array{TSource, TOther}> $mit */

/** @var GenericEnumerable<TResultKey, TResult> */
return new Enumerable(
/** @var SelectIterator<TResultKey, TResult> */
new SelectIterator(
/** @var KeySelectIterator<TResultKey, array{TSource, TOther}> */
new KeySelectIterator(
$mit,
static fn(array $keys): mixed => $keySelector($keys[0], $keys[1]),
static function (mixed $keys) use ($keySelector): mixed {
/** @var array{TIteratorKey, TOtherIteratorKey} $keys */
return $keySelector($keys[0], $keys[1]);
},
),
static fn(array $values): mixed => $resultSelector($values[0], $values[1])
static function (mixed $values) use ($resultSelector): mixed {
/** @var array{TSource, TOther} $values */
return $resultSelector($values[0], $values[1]);
}
)
);
}
Expand Down
5 changes: 3 additions & 2 deletions modules/PIE/src/OrderedEnumerable.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
/**
* @psalm-type NonNegativeInteger = 0|positive-int
*
* @template TKey of NonNegativeInteger
* @template TSource
*
* @extends Enumerable<NonNegativeInteger, TSource>
* @implements GenericOrderedEnumerable<TSource>
* @extends Enumerable<TKey, TSource>
* @implements GenericOrderedEnumerable<TKey, TSource>
*/
class OrderedEnumerable extends Enumerable implements GenericOrderedEnumerable
{
Expand Down

0 comments on commit 88bb2bb

Please sign in to comment.