Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: applyTo() utility function #13

Open
tobia opened this issue Mar 20, 2021 · 2 comments
Open

Proposal: applyTo() utility function #13

tobia opened this issue Mar 20, 2021 · 2 comments

Comments

@tobia
Copy link

tobia commented Mar 20, 2021

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.

@tobia tobia changed the title Proposal: apply() utility function Proposal: applyTo() utility function Mar 20, 2021
@ragboyjr
Copy link
Member

Thanks for the suggestion @tobia, can you find examples of this type of function signature and naming in other functional libraries in php or in other languages?

not necessarily against it, but if there’s a similar concept in other communities that maybe use a different name or something, I’d like to keep consistent if possible.

@tobia
Copy link
Author

tobia commented Mar 20, 2021

Right. I came up with the name and signature myself, because that's what I needed. I'll look into other languages, because the state of PHP functional libraries is quite abysmal. (This is the only libraries that has curried versions of the functions, for example.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants