Skip to content

Proposal: applyTo() utility function #13

@tobia

Description

@tobia

Hello and thank you for writing this library.

Whenever I'm defining a pipeline of functions to be applied immediately to a starting value, instead of being given a name and saved for later, I use the following utility function:

/**
 * Accept an input and some callables, then apply the callables in order.
 *
 * @param   $input      Input to the computation.
 * @param   $callables  Any number of callables to be composed using pipe().
 * @return              Final result of the computation.
 */
function applyTo($input, callable ...$callables) {
    return f\pipe(...$callables)($input);
}

This enables a Bash-like, left-to-right / top-to-bottom style of pipeline definition and application, for those (like me) who find it more readable than the backwards style of compose():

$res = applyTo([1,2,3,4],            // <- input
    c\filter(fn ($x) => $x > 2),   // <- first step
    c\map(fn ($x) => $x * 3),      // ...
    c\toArray,                     // <- last step
);

assert($res == [9, 12]);

Here is a more complex example, showing how to use one applyTo() inside another:

$pages = [
    (object)['slug'=>'about', 'name'=>'About Us'],
    (object)['slug'=>'about', 'name'=>'About You'],
    (object)['slug'=>'news',  'name'=>'Latest News'],
];

$duplicate = applyTo($pages,
    c\groupBy(fn ($page) => $page->slug),
    c\filter(fn ($group) => count($group) > 1),
    c\map(fn ($pages) =>
        "Pages with slug '{$pages[0]->slug}': " . applyTo($pages,
            c\map(fn ($page) => "({$page->name})"),
            c\join(", "),
        )
    ),
    c\join(". "),
);

assert($duplicate == "Pages with slug 'about': (About Us), (About You)");

Do you have any suggestions / critiques? Would you accept a pull request for this function?

I also thought about other calling styles, such as curried: applyTo($input)($fn1, $fn2...) or array: applyTo($input, [$fn1, $fn2...]) but ultimately I decided to keep things simple.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions