functional-php

repository·main·Indexed 24 days ago

https://github.com/lstrojny/functional-php

A set of functional programming primitives for PHP designed to work with arrays and Traversable objects. Inspired by Scala, Dojo, and Underscore.js, it provides utilities for collection manipulation (select, reject, every, some), partial application (partial_left, partial_right, partial_any), currying (curry, curry_n), and function composition (juxt, converge), all located within the Functional namespace.

Tokens
9.2K
Snippets
48
Records
51
Agent score
34%

What's inside functional-php

  1. Create partially applied functions with partial_left() and partial_right()

    main

    Partial application allows you to create a new function by binding some arguments of an existing function.

    • partial_left($fn, ...$args): Binds arguments to the beginning of the function.
    • partial_right($fn, ...$args): Binds arguments to the end of the function.

    Example:

    use function Functional\partial_left;
    
    $subtractor = fn ($a, $b) => $a - $b;
    $partiallyAppliedSubtractor = partial_left($subtractor, 20);
    $partiallyAppliedSubtractor(10); // 10
  2. Core concepts of functional-php

    main

    functional-php provides a set of functional primitives inspired by Scala, Dojo, and Underscore.js. Key characteristics include:

    • Compatibility: Works with standard PHP arrays and any object implementing the Traversable interface.
    • Consistent Interface: For functions that take a collection and a callback, the signature is always (collection, callback). The callback is always passed three arguments in this order: $value, $index, and $collection.
    • Callback Support: Supports both standard callbacks and PHP 5.3+ closures.
    • Namespace: All functions are located in the Functional namespace to prevent naming conflicts with other libraries or extensions.
  3. Import Functional PHP functions

    main

    To use Functional PHP functions without using their fully qualified names, you can use the use Functional as F; statement at the top of your file, or import specific functions using use function Functional\function_name;. The latter is the preferred method for PHP 5.6+.

    Example:

    use function Functional\map;
    
    $emails = map($users, fn ($user) => $user->getEmail());
  4. Find indexes in collections with indexes_of()

    main

    The indexes_of() function returns a list of array indexes that either match a provided predicate (callable) or are strictly equal to a passed value. It returns an empty array if no matches are found.

    use function Functional\indexes_of;
    
    // Returns array(0, 2)
    $indexes = indexes_of(['value', 'value2', 'value'], 'value');
  5. Flip argument order with flip()

    main

    The flip() function returns a new function with the argument order of the original function reversed. This is particularly useful when currying functions like filter to allow providing the predicate first and the data last.

    use function Functional\flip;
    use function Functional\curry;
    
    $filter = curry(flip('Functional\filter'));
    $getEven = $filter(fn ($number) => $number % 2 === 0);
    $getEven([1, 2, 3, 4]); // [2, 4]
  6. Invoke callbacks and methods with access functions

    main

    Functional PHP provides several helpers to invoke callbacks on values or call methods on objects/collections:

    • with(mixed $value, callable $callback, bool $invokeValue = true, mixed $default = null): Invokes a callback on $value only if $value is not null. Returns the callback's result or $default (defaults to null) if $value is null.
    • invoke_if(mixed $object, string $methodName, array $methodArguments = [], mixed $defaultValue = null): Invokes $methodName on $object if it is an object and the method is public. Otherwise, returns $defaultValue.
    • invoke(array|Traversable $collection, string $methodName, array $methodArguments = []): Invokes $methodName on every object in the $collection and returns an array of results.
    • invoke_first(array|Traversable $collection, string $methodName, array $methodArguments = []): Invokes $methodName on the first object in the collection that actually contains that method.
    • invoke_last(array|Traversable $collection, string $methodName, array $methodArguments = []): Invokes $methodName on the last object in the collection that actually contains that method.
    • invoker(string $method, array $methodArguments = []): Returns a new callable that, when called with an object, invokes $method on that object with the pre-defined $methodArguments.
    use function Functional\with;
    use function Functional\invoke_if;
    use function Functional\invoke;
    use function Functional\invoke_first;
    use function Functional\invoke_last;
    use function Functional\invoker;
    
    // with()
    $retval = with(create_user('John Doe'), function ($user) {
        send_welcome_email($user);
        return 'my_result';
    });
    
    // invoke_if()
    $userId = invoke_if($user, 'getId', [], 0);
    
    // invoke()
    invoke($meetings, 'addAttendee', $user); 
    
    // invoke_first() & invoke_last()
    invoke_first($meetings, 'delayEvent', [30]);
    invoke_last($meetings, 'changeRoom', ['Room 3']);
    
    // invoker()
    $setLocationToMunich = invoker('updateLocation', ['Munich', 'Germany']);
    $setLocationToMunich($user); 
  7. Check for strict boolean values with true() and false()

    main

    The true() and false() functions return true only if all elements in the collection are strictly true or strictly false, respectively.

    Signatures: bool Functional\true(array|Traversable $collection) bool Functional\false(array|Traversable $collection)

    use function Functional\true;
    use function Functional\false;
    
    // Returns true
    true([true, true]);
    // Returns false
    true([true, 1]);
    
    // Returns true
    false([false, false, false]);
    // Returns false
    false([false, 0, null, false]);
  8. Compose functions with compose()

    main

    The compose() function returns a new function that is the composition of multiple functions. When the composed function is called, the arguments are passed to the last function in the list, and the result is passed to the second-to-last, and so on (right-to-left composition).

    use function Functional\compose;
    
    $plus2 = fn ($x) => $x + 2;
    $times4 = fn ($x) => $x * 4;
    
    $composed = compose($plus2, $times4);
    array_map($composed, [1, 2, 5, 8]); // [12, 16, 28, 40]