-
-
Notifications
You must be signed in to change notification settings - Fork 71
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: introduce
first_opt()
, first_key_opt()
, last_opt()
, `last…
…_key_opt()` and `search_opt()` (#467) * feat: introduce `first_opt()`, `first_key_opt()`, `last_opt()`, `last_key_opt()` and `search_opt()` * Update src/Psl/Iter/last_opt.php Co-authored-by: Saif Eddin Gmati <29315886+azjezz@users.noreply.github.com> * Update src/Psl/Iter/search_opt.php * example --------- Co-authored-by: Saif Eddin Gmati <29315886+azjezz@users.noreply.github.com>
- Loading branch information
Showing
12 changed files
with
410 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Psl\Iter; | ||
|
||
use Psl\Option\Option; | ||
|
||
/** | ||
* Returns the first key of an iterable wrapped in {@see Option::some}, | ||
* if the iterable is empty, {@see Option::none} will be returned. | ||
* | ||
* @param iterable<Tk, Tv> $iterable | ||
* | ||
* @template Tk | ||
* @template Tv | ||
* | ||
* @return Option<Tk> | ||
*/ | ||
function first_key_opt(iterable $iterable): Option | ||
{ | ||
foreach ($iterable as $k => $_) { | ||
return Option::some($k); | ||
} | ||
|
||
return Option::none(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Psl\Iter; | ||
|
||
use Psl\Option\Option; | ||
|
||
/** | ||
* Returns the first element of an iterable wrapped in {@see Option::some}, | ||
* if the iterable is empty, {@see Option::none} will be returned. | ||
* | ||
* @template T | ||
* | ||
* @param iterable<T> $iterable | ||
* | ||
* @return Option<T> | ||
*/ | ||
function first_opt(iterable $iterable): Option | ||
{ | ||
foreach ($iterable as $v) { | ||
return Option::some($v); | ||
} | ||
|
||
return Option::none(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Psl\Iter; | ||
|
||
use Psl\Option\Option; | ||
|
||
/** | ||
* Returns the first key of an iterable wrapped in {@see Option::some}, | ||
* if the iterable is empty, {@see Option::none} will be returned. | ||
* | ||
* @template Tk | ||
* @template Tv | ||
* | ||
* @param iterable<Tk, Tv> $iterable | ||
* | ||
* @return Option<Tk> | ||
*/ | ||
function last_key_opt(iterable $iterable): Option | ||
{ | ||
$last = Option::none(); | ||
foreach ($iterable as $k => $_) { | ||
$last = Option::some($k); | ||
} | ||
|
||
return $last; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Psl\Iter; | ||
|
||
use Psl\Option\Option; | ||
|
||
/** | ||
* Returns the last element of an iterable wrapped in {@see Option::some}, | ||
* if the iterable is empty, {@see Option::none} will be returned. | ||
* | ||
* @template Tv | ||
* | ||
* @param iterable<Tv> $iterable | ||
* | ||
* @return Option<Tv> | ||
*/ | ||
function last_opt(iterable $iterable): Option | ||
{ | ||
$last = Option::none(); | ||
foreach ($iterable as $v) { | ||
$last = Option::some($v); | ||
} | ||
|
||
return $last; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Psl\Iter; | ||
|
||
use Closure; | ||
use Psl\Option\Option; | ||
|
||
/** | ||
* Searches an iterable until a predicate returns true, then returns | ||
* the value of the matching element wrapped in {@see Option::some}. | ||
* If a predicate never returns true, {@see Option::none} will be returned. | ||
* | ||
* Examples: | ||
* | ||
* Iter\search_opt(['foo', 'bar', 'baz'], fn($v) => 'baz' === $v) | ||
* => Option::some('baz') | ||
* | ||
* Iter\search_opt(['foo', 'bar', 'baz'], fn($v) => 'qux' === $v) | ||
* => Option::none() | ||
* | ||
* @template T | ||
* | ||
* @param iterable<T> $iterable The iterable to search | ||
* @param (Closure(T): bool) $predicate | ||
* | ||
* @return Option<T> | ||
*/ | ||
function search_opt(iterable $iterable, Closure $predicate): Option | ||
{ | ||
foreach ($iterable as $value) { | ||
if ($predicate($value)) { | ||
return Option::some($value); | ||
} | ||
} | ||
|
||
return Option::none(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Psl\Tests\Unit\Iter; | ||
|
||
use PHPUnit\Framework\TestCase; | ||
use Psl\Collection; | ||
use Psl\Iter; | ||
use SplDoublyLinkedList; | ||
|
||
final class FirstKeyOptTest extends TestCase | ||
{ | ||
/** | ||
* @dataProvider provideDataSome | ||
*/ | ||
public function testFirstKeyOptSome($expected, iterable $iterable): void | ||
{ | ||
$result = Iter\first_key_opt($iterable); | ||
|
||
static::assertSame($expected, $result->unwrap()); | ||
} | ||
|
||
public function provideDataSome(): iterable | ||
{ | ||
yield ['a', ['a' => 'b']]; | ||
yield [0, ['a', 'b']]; | ||
yield [0, new Collection\Vector(['a', 'b'])]; | ||
yield [0, new Collection\Vector(['a' => 'b'])]; | ||
yield ['a', new Collection\Map(['a' => 'b'])]; | ||
yield [null, (static function () { | ||
yield null => null; | ||
})()]; | ||
} | ||
|
||
/** | ||
* @dataProvider provideDataNone | ||
*/ | ||
public function testFirstKeyOptNone(iterable $iterable): void | ||
{ | ||
$result = Iter\first_key_opt($iterable); | ||
|
||
static::assertTrue($result->isNone()); | ||
} | ||
|
||
public function provideDataNone(): iterable | ||
{ | ||
yield [[]]; | ||
yield [new SplDoublyLinkedList()]; | ||
yield [(static function () { | ||
return; | ||
yield; | ||
})()]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Psl\Tests\Unit\Iter; | ||
|
||
use PHPUnit\Framework\TestCase; | ||
use Psl\Collection; | ||
use Psl\Iter; | ||
use SplDoublyLinkedList; | ||
|
||
final class FirstOptTest extends TestCase | ||
{ | ||
/** | ||
* @dataProvider provideDataSome | ||
*/ | ||
public function testFirstSome($expected, iterable $iterable): void | ||
{ | ||
$result = Iter\first_opt($iterable); | ||
|
||
static::assertSame($expected, $result->unwrap()); | ||
} | ||
|
||
public function provideDataSome(): iterable | ||
{ | ||
yield ['b', ['a' => 'b', 'c' => 'd']]; | ||
yield ['a', ['a', 'b']]; | ||
yield ['a', new Collection\Vector(['a', 'b'])]; | ||
yield ['b', new Collection\Vector(['b'])]; | ||
yield ['b', new Collection\Map(['a' => 'b', 'c' => 'd'])]; | ||
yield [null, (static function () { | ||
yield null => null; | ||
})()]; | ||
} | ||
|
||
/** | ||
* @dataProvider provideDataNone | ||
*/ | ||
public function testFirstNone(iterable $iterable): void | ||
{ | ||
$result = Iter\first_opt($iterable); | ||
|
||
static::assertTrue($result->isNone()); | ||
} | ||
|
||
public function provideDataNone(): iterable | ||
{ | ||
yield [[]]; | ||
yield [new SplDoublyLinkedList()]; | ||
yield [(static function () { | ||
return; | ||
yield; | ||
})()]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Psl\Tests\Unit\Iter; | ||
|
||
use PHPUnit\Framework\TestCase; | ||
use Psl\Iter; | ||
use Psl\Vec; | ||
|
||
final class LastKeyOptTest extends TestCase | ||
{ | ||
/** | ||
* @dataProvider provideDataSome | ||
*/ | ||
public function testLastKeySome($expected, iterable $iterable): void | ||
{ | ||
$result = Iter\last_key_opt($iterable); | ||
|
||
static::assertSame($expected, $result->unwrap()); | ||
} | ||
|
||
public function provideDataSome(): iterable | ||
{ | ||
yield [3, [1, 2, 3, 4]]; | ||
yield [3, Iter\to_iterator([1, 2, 3, 4])]; | ||
yield [3, Vec\range(1, 4)]; | ||
yield [4, Vec\range(4, 8)]; | ||
yield [4, Iter\to_iterator(Vec\range(4, 8))]; | ||
yield [0, [null]]; | ||
yield [1, [null, null]]; | ||
yield [[1, 2], (static fn () => yield [1, 2] => 'hello')()]; | ||
} | ||
|
||
/** | ||
* @dataProvider provideDataNone | ||
*/ | ||
public function testLastKeyNone(iterable $iterable): void | ||
{ | ||
$result = Iter\last_key_opt($iterable); | ||
|
||
static::assertTrue($result->isNone()); | ||
} | ||
|
||
public function provideDataNone(): iterable | ||
{ | ||
yield [[]]; | ||
} | ||
} |
Oops, something went wrong.