fix strict type ignored when mapping or filtering arrays (#196)

This commit is contained in:
Saif Eddin Gmati 2021-05-19 12:49:49 +01:00 committed by GitHub
parent 963a0bb6fd
commit 60683bf0f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 116 additions and 24 deletions

View File

@ -17,13 +17,13 @@
- [concat](./../../src/Psl/Vec/concat.php#L17)
- [enumerate](./../../src/Psl/Vec/enumerate.php#L17)
- [fill](./../../src/Psl/Vec/fill.php#L24)
- [filter](./../../src/Psl/Vec/filter.php#L30)
- [filter_keys](./../../src/Psl/Vec/filter_keys.php#L31)
- [filter](./../../src/Psl/Vec/filter.php#L34)
- [filter_keys](./../../src/Psl/Vec/filter_keys.php#L37)
- [filter_nulls](./../../src/Psl/Vec/filter_nulls.php#L20)
- [filter_with_key](./../../src/Psl/Vec/filter_with_key.php#L34)
- [filter_with_key](./../../src/Psl/Vec/filter_with_key.php#L40)
- [flat_map](./../../src/Psl/Vec/flat_map.php#L16)
- [keys](./../../src/Psl/Vec/keys.php#L20)
- [map](./../../src/Psl/Vec/map.php#L27)
- [map](./../../src/Psl/Vec/map.php#L31)
- [map_with_key](./../../src/Psl/Vec/map_with_key.php#L27)
- [partition](./../../src/Psl/Vec/partition.php#L18)
- [range](./../../src/Psl/Vec/range.php#L50)

View File

@ -37,7 +37,13 @@ function filter(iterable $iterable, ?callable $predicate = null): array
$predicate = $predicate ?? Closure::fromCallable('Psl\Internal\boolean');
if (is_array($iterable)) {
return array_filter($iterable, $predicate);
return array_filter(
$iterable,
/**
* @param Tv $v
*/
static fn($v): bool => $predicate($v)
);
}
$result = [];

View File

@ -39,7 +39,14 @@ function filter_keys(iterable $iterable, ?callable $predicate = null): array
$predicate = $predicate ?? Closure::fromCallable('Psl\Internal\boolean');
if (is_array($iterable)) {
return array_filter($iterable, $predicate, ARRAY_FILTER_USE_KEY);
return array_filter(
$iterable,
/**
* @param Tk $k
*/
static fn($k): bool => $predicate($k),
ARRAY_FILTER_USE_KEY
);
}
$result = [];

View File

@ -10,7 +10,7 @@ namespace Psl\Iter;
* @template Tk
* @template Tv
*
* @param iterable<Tk, Tv> $iterable,
* @param iterable<Tk, Tv> $iterable
* @param Tk $key
*/
function contains_key(iterable $iterable, $key): bool

View File

@ -6,6 +6,10 @@ namespace Psl\Vec;
use Closure;
use function array_filter;
use function array_values;
use function is_array;
/**
* Returns a vec containing only the values for which the given predicate
* returns `true`.
@ -31,6 +35,16 @@ function filter(iterable $iterable, ?callable $predicate = null): array
{
/** @var (callable(T): bool) $predicate */
$predicate = $predicate ?? Closure::fromCallable('Psl\Internal\boolean');
if (is_array($iterable)) {
return array_values(array_filter(
$iterable,
/**
* @param T $t
*/
static fn($t): bool => $predicate($t)
));
}
$result = [];
foreach ($iterable as $v) {
if ($predicate($v)) {

View File

@ -6,6 +6,12 @@ namespace Psl\Vec;
use Closure;
use function array_filter;
use function array_values;
use function is_array;
use const ARRAY_FILTER_USE_KEY;
/**
* Returns a vec containing only the values for which the given predicate
* returns `true`.
@ -32,6 +38,17 @@ function filter_keys(iterable $iterable, ?callable $predicate = null): array
{
/** @var (callable(Tk): bool) $predicate */
$predicate = $predicate ?? Closure::fromCallable('Psl\Internal\boolean');
if (is_array($iterable)) {
return array_values(array_filter(
$iterable,
/**
* @param Tk $t
*/
static fn($t): bool => $predicate($t),
ARRAY_FILTER_USE_KEY
));
}
$result = [];
foreach ($iterable as $k => $v) {
if ($predicate($k)) {

View File

@ -19,13 +19,12 @@ namespace Psl\Vec;
*/
function filter_nulls(iterable $iterable): array
{
/** @var list<T> $result */
$result = [];
foreach ($iterable as $value) {
if (null !== $value) {
$result[] = $value;
}
}
return $result;
/** @var list<T> */
return filter(
$iterable,
/**
* @param T|null $value
*/
static fn($value): bool => null !== $value
);
}

View File

@ -6,6 +6,12 @@ namespace Psl\Vec;
use Psl;
use function array_filter;
use function array_values;
use function is_array;
use const ARRAY_FILTER_USE_BOTH;
/**
* Returns a vec containing only the values for which the given predicate
* returns `true`.
@ -40,6 +46,18 @@ function filter_with_key(iterable $iterable, ?callable $predicate = null): array
*/
static fn ($_k, $v): bool => Psl\Internal\boolean($v);
if (is_array($iterable)) {
return array_values(array_filter(
$iterable,
/**
* @param Tv $v
* @param Tk $k
*/
static fn($v, $k): bool => $predicate($k, $v),
ARRAY_FILTER_USE_BOTH
));
}
$result = [];
foreach ($iterable as $k => $v) {
if ($predicate($k, $v)) {

View File

@ -4,6 +4,10 @@ declare(strict_types=1);
namespace Psl\Vec;
use function array_map;
use function array_values;
use function is_array;
/**
* Applies a mapping function to all values of an iterable.
*
@ -26,6 +30,16 @@ namespace Psl\Vec;
*/
function map(iterable $iterable, callable $function): array
{
if (is_array($iterable)) {
return array_values(array_map(
/**
* @param Tv $v
*/
static fn($v) => $function($v),
$iterable
));
}
$result = [];
foreach ($iterable as $value) {
$result[] = $function($value);

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Psl\Tests\Dict;
use PHPUnit\Framework\TestCase;
use Psl\Collection;
use Psl\Dict;
final class MapTest extends TestCase
@ -12,9 +13,9 @@ final class MapTest extends TestCase
/**
* @dataProvider provideData
*/
public function testMap(array $expected, array $array, callable $function): void
public function testMap(array $expected, iterable $iterable, callable $function): void
{
$result = Dict\map($array, $function);
$result = Dict\map($iterable, $function);
static::assertSame($expected, $result);
}
@ -24,6 +25,8 @@ final class MapTest extends TestCase
yield [[1, 2, 3], [1, 2, 3], static fn (int $v): int => $v];
yield [[2, 4, 6], [1, 2, 3], static fn (int $v): int => $v * 2];
yield [['1', '2', '3'], [1, 2, 3], static fn (int $v): string => (string)$v];
yield [['1', '2', '3'], Collection\Map::fromArray([1, 2, 3]), static fn (int $v): string => (string)$v];
yield [[], Collection\Map::fromArray([]), static fn (int $v): string => (string)$v];
yield [[], [], static fn (int $v): string => (string)$v];
}
}

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Psl\Tests\Vec;
use PHPUnit\Framework\TestCase;
use Psl\Collection;
use Psl\Vec;
final class FilterKeysTest extends TestCase
@ -12,9 +13,9 @@ final class FilterKeysTest extends TestCase
/**
* @dataProvider provideData
*/
public function testFilter(array $expected, array $array, ?callable $predicate = null): void
public function testFilter(array $expected, iterable $iterable, ?callable $predicate = null): void
{
$result = Vec\filter_keys($array, $predicate);
$result = Vec\filter_keys($iterable, $predicate);
static::assertSame($expected, $result);
}
@ -25,6 +26,9 @@ final class FilterKeysTest extends TestCase
yield [['b'], ['a', 'b']];
yield [['a'], ['a', 'b'], static fn (int $k): bool => $k !== 1];
yield [['b'], ['a', 'b'], static fn (int $k): bool => $k !== 0];
yield [['b'], Collection\Vector::fromArray(['a', 'b']), static fn (int $k): bool => $k !== 0];
yield [[], Collection\Vector::fromArray(['a', 'b']), static fn (int $k): bool => false];
yield [[], Collection\Vector::fromArray([]), static fn (int $k): bool => false];
yield [[], ['a', 'b'], static fn (int $_) => false];
yield [['a', 'b'], ['a', 'b'], static fn (int $_): bool => true];
}

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Psl\Tests\Vec;
use PHPUnit\Framework\TestCase;
use Psl\Collection;
use Psl\Vec;
final class FilterWithKeyTest extends TestCase
@ -12,9 +13,9 @@ final class FilterWithKeyTest extends TestCase
/**
* @dataProvider provideData
*/
public function testFilterWithKey(array $expected, array $array, ?callable $predicate = null): void
public function testFilterWithKey(array $expected, iterable $iterable, ?callable $predicate = null): void
{
$result = Vec\filter_with_key($array, $predicate);
$result = Vec\filter_with_key($iterable, $predicate);
static::assertSame($expected, $result);
}
@ -25,6 +26,10 @@ final class FilterWithKeyTest extends TestCase
yield [['a', 'b'], ['a', 'b']];
yield [[], ['a', 'b'], static fn (int $_k, string $_v) => false];
yield [['a', 'b'], ['a', 'b'], static fn (int $_k, string $_v): bool => true];
yield [[], Collection\Vector::fromArray([])];
yield [['a', 'b'], Collection\Vector::fromArray(['a', 'b'])];
yield [[], Collection\Vector::fromArray(['a', 'b']), static fn (int $_k, string $_v) => false];
yield [['a', 'b'], Collection\Vector::fromArray(['a', 'b']), static fn (int $_k, string $_v): bool => true];
yield [['a'], ['a', 'b'], static fn (int $k, string $v): bool => 'b' !== $v];
yield [[], ['a', 'b'], static fn (int $k, string $v): bool => 'b' !== $v && 0 !== $k];
yield [['a'], ['a', 'b'], static fn (int $k, string $v): bool => 'b' !== $v && 1 !== $k];

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Psl\Tests\Vec;
use PHPUnit\Framework\TestCase;
use Psl\Collection;
use Psl\Vec;
final class MapTest extends TestCase
@ -12,9 +13,9 @@ final class MapTest extends TestCase
/**
* @dataProvider provideData
*/
public function testMap(array $expected, array $array, callable $function): void
public function testMap(array $expected, iterable $iterable, callable $function): void
{
$result = Vec\map($array, $function);
$result = Vec\map($iterable, $function);
static::assertSame($expected, $result);
}
@ -25,5 +26,9 @@ final class MapTest extends TestCase
yield [[2, 4, 6], [1, 2, 3], static fn (int $v): int => $v * 2];
yield [['1', '2', '3'], [1, 2, 3], static fn (int $v): string => (string)$v];
yield [[], [], static fn (int $v): string => (string)$v];
yield [[1, 2, 3], Collection\Vector::fromArray([1, 2, 3]), static fn (int $v): int => $v];
yield [[2, 4, 6], Collection\Vector::fromArray([1, 2, 3]), static fn (int $v): int => $v * 2];
yield [['1', '2', '3'], Collection\Vector::fromArray([1, 2, 3]), static fn (int $v): string => (string)$v];
yield [[], Collection\Vector::fromArray([]), static fn (int $v): string => (string)$v];
}
}