Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

Fun

Introduction

The Fun component brings functional programming into PHP.

Usage

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);

API

Functions

  • [@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');