On Thu, Oct 1, 2015 at 10:47 AM, Rowan Collins <rowan.coll...@gmail.com> wrote:
> Levi Morrison wrote on 01/10/2015 16:52:
>>
>> This is
>> close:https://github.com/morrisonlevi/Algorithm/blob/master/src/reduce.php
>
>
> When would you store or pass around the intermediate callback (the result of
> reduce($initial)) without immediately invoking it with a callback? If you
> just run "reduce($initial)($my_fn)($data)", it seems no more useful than
> "reduce(42, $my_fn, $data)", which would be more efficient internally.
>
> If anything, I can imagine wanting to write $my_reduce = reduce($my_fn) and
> then $my_reduce($initial, $data), but that's still 2 steps rather than 3.
>
> Genuine question, not a criticism - this functional(?) style of composition
> is not something I'm very familiar with. (For the same reason, I struggle to
> read that function definition no matter which syntax it's expressed in.)

I've worked out what I think are elegant definitions that are highly
composable and usable by iterators and arrays alike. For example, it's
common in our code base to do a filter followed by a map (or series of
maps) and sometimes followed by a reduce. Here's a simplified example,
with definitions taken from the linked repository:

    $algorithm = chain(
        filter(function($x) => $x % 2 > 0),
        map(function($x) => $x * 2),
        sum()
    );

    $algorithm([1,2,3]);

If you understand the (very common) algorithms filter and map then
this is trivial to understand. More than that, it's easy to write and
very difficult to introduce bugs into it since you are writing very
simple functions that perform a single task.

Chain works is because the functions passed to it accept iterables as
their only parameter and return either an another iterable or a
reducing function (in this example sum is the reducer). This is why
the functions are returning closures that accept only one parameter.

This can be done with a binding function with more traditional
definitions like Nikita Popov's iter library, or by writing inline
closures:

    $algorithm = chain(
        // using a bind function
        bind('iter\\fn\\filter', function($x) => $x % 2 > 0),
        bind('iter\\fn\\map', function($x) => $x * 2),

        // using a closure (showed the closure with this one because
        // the parameter order doesn't work well with bind)
        function($input) => iter\fn\reduce(function($x, $y) => $x +
$y, $input, 0)
    );

    $algorithm([1,2,3]);

There's a lot more noise here, which is why the library I linked
returns a series of closures. Both are valid, but if you are going to
write this particular style then the closure style has less noise when
called.

Hopefully that was helpful.

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to