From 77e9645956c4e2248edbb5fd0978f888b9f34bb9 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 21 Nov 2023 22:42:40 +0100 Subject: [PATCH] Iterables: $else [WIP] --- src/Utils/Iterables.php | 16 ++++++++-------- tests/Utils/Iterables.first().phpt | 4 ++++ tests/Utils/Iterables.firstKey().phpt | 4 ++++ 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/Utils/Iterables.php b/src/Utils/Iterables.php index 8a66e722a..3fd96c4cf 100644 --- a/src/Utils/Iterables.php +++ b/src/Utils/Iterables.php @@ -48,38 +48,38 @@ public static function containsKey(iterable $iterable, mixed $key): bool /** - * Returns the first item (matching the specified predicate if given) or null if there is no such item. - * The callback has the signature `function ($value, $key, $iterable): bool`. + * Returns the first item (matching the specified predicate if given). If there is no such item, it returns result of invoking $else or null. + * The $predicate has the signature `function ($value, $key, $iterable): bool`. * @template T * @param iterable $iterable * @return ?T */ - public static function first(iterable $iterable, ?callable $predicate = null): mixed + public static function first(iterable $iterable, ?callable $predicate = null, ?callable $else = null): mixed { foreach ($iterable as $k => $v) { if (!$predicate || $predicate($v, $k, $iterable)) { return $v; } } - return null; + return $else ? $else() : null; } /** - * Returns the key of first item (matching the specified predicate if given) or null if there is no such item. - * The callback has the signature `function ($value, $key, $iterable): bool`. + * Returns the key of first item (matching the specified predicate if given). If there is no such item, it returns result of invoking $else or null. + * The $predicate has the signature `function ($value, $key, $iterable): bool`. * @template T * @param iterable $iterable * @return ?T */ - public static function firstKey(iterable $iterable, ?callable $predicate = null): mixed + public static function firstKey(iterable $iterable, ?callable $predicate = null, ?callable $else = null): mixed { foreach ($iterable as $k => $v) { if (!$predicate || $predicate($v, $k, $iterable)) { return $k; } } - return null; + return $else ? $else() : null; } diff --git a/tests/Utils/Iterables.first().phpt b/tests/Utils/Iterables.first().phpt index 4665f6b0b..caa096be6 100644 --- a/tests/Utils/Iterables.first().phpt +++ b/tests/Utils/Iterables.first().phpt @@ -37,3 +37,7 @@ test('with predicate', function () { test('predicate arguments', function () { Iterables::first([2 => 'x'], fn() => Assert::same(['x', 2, [2 => 'x']], func_get_args())); }); + +test('else', function () { + Assert::same(123, Iterables::first(new ArrayIterator([]), else: fn() => 123)); +}); diff --git a/tests/Utils/Iterables.firstKey().phpt b/tests/Utils/Iterables.firstKey().phpt index fdd42f8d3..1f3d63991 100644 --- a/tests/Utils/Iterables.firstKey().phpt +++ b/tests/Utils/Iterables.firstKey().phpt @@ -37,3 +37,7 @@ test('with predicate', function () { test('predicate arguments', function () { Iterables::firstKey([2 => 'x'], fn() => Assert::same(['x', 2, [2 => 'x']], func_get_args())); }); + +test('else', function () { + Assert::same(123, Iterables::firstKey(new ArrayIterator([]), else: fn() => 123)); +});