Skip to content

Commit

Permalink
fix strict type ignored when mapping or filtering arrays (#196)
Browse files Browse the repository at this point in the history
  • Loading branch information
azjezz committed May 19, 2021
1 parent 963a0bb commit 60683bf
Show file tree
Hide file tree
Showing 13 changed files with 116 additions and 24 deletions.
8 changes: 4 additions & 4 deletions docs/component/vec.md
Expand Up @@ -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)
Expand Down
8 changes: 7 additions & 1 deletion src/Psl/Dict/filter.php
Expand Up @@ -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 = [];
Expand Down
9 changes: 8 additions & 1 deletion src/Psl/Dict/filter_keys.php
Expand Up @@ -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 = [];
Expand Down
2 changes: 1 addition & 1 deletion src/Psl/Iter/contains_key.php
Expand Up @@ -10,7 +10,7 @@
* @template Tk
* @template Tv
*
* @param iterable<Tk, Tv> $iterable,
* @param iterable<Tk, Tv> $iterable
* @param Tk $key
*/
function contains_key(iterable $iterable, $key): bool
Expand Down
14 changes: 14 additions & 0 deletions src/Psl/Vec/filter.php
Expand Up @@ -6,6 +6,10 @@

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`.
Expand All @@ -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)) {
Expand Down
17 changes: 17 additions & 0 deletions src/Psl/Vec/filter_keys.php
Expand Up @@ -6,6 +6,12 @@

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`.
Expand All @@ -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)) {
Expand Down
17 changes: 8 additions & 9 deletions src/Psl/Vec/filter_nulls.php
Expand Up @@ -19,13 +19,12 @@
*/
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
);
}
18 changes: 18 additions & 0 deletions src/Psl/Vec/filter_with_key.php
Expand Up @@ -6,6 +6,12 @@

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`.
Expand Down Expand Up @@ -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)) {
Expand Down
14 changes: 14 additions & 0 deletions src/Psl/Vec/map.php
Expand Up @@ -4,6 +4,10 @@

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.
*
Expand All @@ -26,6 +30,16 @@
*/
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);
Expand Down
7 changes: 5 additions & 2 deletions tests/Psl/Dict/MapTest.php
Expand Up @@ -5,16 +5,17 @@
namespace Psl\Tests\Dict;

use PHPUnit\Framework\TestCase;
use Psl\Collection;
use Psl\Dict;

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);
}
Expand All @@ -24,6 +25,8 @@ public function provideData(): iterable
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];
}
}
8 changes: 6 additions & 2 deletions tests/Psl/Vec/FilterKeysTest.php
Expand Up @@ -5,16 +5,17 @@
namespace Psl\Tests\Vec;

use PHPUnit\Framework\TestCase;
use Psl\Collection;
use Psl\Vec;

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);
}
Expand All @@ -25,6 +26,9 @@ public function provideData(): iterable
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];
}
Expand Down
9 changes: 7 additions & 2 deletions tests/Psl/Vec/FilterWithKeyTest.php
Expand Up @@ -5,16 +5,17 @@
namespace Psl\Tests\Vec;

use PHPUnit\Framework\TestCase;
use Psl\Collection;
use Psl\Vec;

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);
}
Expand All @@ -25,6 +26,10 @@ public function provideData(): iterable
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];
Expand Down
9 changes: 7 additions & 2 deletions tests/Psl/Vec/MapTest.php
Expand Up @@ -5,16 +5,17 @@
namespace Psl\Tests\Vec;

use PHPUnit\Framework\TestCase;
use Psl\Collection;
use Psl\Vec;

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);
}
Expand All @@ -25,5 +26,9 @@ public function provideData(): iterable
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];
}
}

0 comments on commit 60683bf

Please sign in to comment.