The Fun component brings functional programming into PHP.
use Psl;
use Psl\Fun;
$admin = Fun\when(
static fn(User $user): bool => $user->isAdmin(),
Fun\identity(),
static fn(User $user): User => $user->withRole(Role::Admin)
)($user);
-
[
@template T
php]
[@pure
php]
[Fun\identity(): (Closure(T): T)
php]Create a closure that returns the value passed to it as an argument.
use Psl; use Psl\Fun; use Psl\Collection; $vector = Collection\Vector::fromArray([1, 2, 3]); $id = Fun\identity(); $vector2 = $id($vector); Psl\invariant($vector === $vector2, '$vector and $vector2 are the same');
-
[
@template I
php]
[@template O
php]
[@template R
php]
[@pure
php]
[Fun\after((Closure(I): O) $first, (Closure(O): R) $next): (Closure(I): R)
php]Returns a closure that calls the next functions with the result of the first one.
use Psl; use Psl\Fun; $calculate = Fun\after( static fn(int $a): int => $a + 2, static fn(int $c): int => $c * 2 ); Psl\invariant($calculate(1) === 6, 'Result is 6'); Psl\invariant($calculate(2) === 8, 'Result is 8');
-
[
@template T
php]
[@pure
php]
[Fun\lazy((Closure(): T) $initializer): (Closure(): T)
php]Returns a closure that can be used for lazy evaluation.
use Psl; use Psl\IO; use Psl\Fun; $lazy = Fun\lazy(static function(): int { IO\write_line('evaluated.'); return 1; }); Psl\invariant($lazy() === 1, 'Result is 1'); Psl\invariant($lazy() === 1, 'Result is 1'); // Output: // evaluated.
This function can also be used to create lazy streams.
use Psl; use Psl\Dict; use Psl\Fun; $stream = Fun\lazy(static function(): iterable { $i = 0; while (true) { yield ++$i; } }); $a = Dict\take($stream(), 10); // [1...10] $b = Dict\take($stream(), 20); // [11...30]
-
[
@template T
php]
[@pure
php]
[Fun\pipe((Closure(T): T) ...$stages): (Closure(): T)
php]Performs left-to-right function composition.
use Psl; use Psl\Fun; $add = static fn(int $a): int => $a + 5; $mul = static fn(int $a): int => $a * 3; $div = static fn(int $a): int => $a / 2; $pipe = Fun\pipe($add, $mul, $div); Psl\invariant($pipe(1) === 9, 'Result is 9');
-
[
@pure
php]
[Fun\rethrow(): (Closure(Exception): never)
php]Returns a closure that rethrows the exception passed to it.
use Psl; use Psl\Fun; $rethrow = Fun\rethrow(); try { $rethrow(new Exception('foo')); } catch (Exception $e) { Psl\invariant($e->getMessage() === 'foo', 'Exception message is "foo"'); }
use Psl; use Psl\Fun; use Psl\Async; $awaitable = Async\run(static fn() => throw new Exception('foo')) ->then(Fun\identity(), Fun\rethrow()); try { $awaitable->await(); } catch (Exception $e) { Psl\invariant($e->getMessage() === 'foo', 'Exception message is "foo"'); }
-
[
@template T
php]
[@pure
php]
[Fun\tap((Closure(T): void) $callback): (Closure(T): T)
php]Returns a closure that calls the callback with the value passed to it and returns the value.
use Psl; use Psl\Fun; $tap = Fun\tap(static fn(string $a) => IO\write_line($a)); Psl\invariant($tap('hello') === 'hello', 'Result is "hello"'); // Output: // hello
-
[
@template Ti
php]
[@template To
php]
[@pure
php]
[Fun\when((Closure(Ti): bool) $condition, (Closure(Ti): To) $then, (Closure(Ti): To) $else): (Closure(Ti): To)
php]Returns a closure that returns the result of the [
$then
php] function if the condition is true, otherwise the result of the [$else
php] function.use Psl; use Psl\Fun; $when = Fun\when( static fn(int $a): bool => $a > 0, static fn(int $a): int => $a * 2, static fn(int $a): int => $a * 3 ); Psl\invariant($when(1) === 2, 'Result is 2'); Psl\invariant($when(-1) === -3, 'Result is -3');