rfc:short_closures

This is an old revision of the document!


PHP RFC: Short Closures

Introduction

When writing partial functions, quick Closures to be applied to an array, or just a minimal lambda to do nothing, we always have to do this tedious work and write function () use ($thousand, $vars) { return $thousand * $vars; } — This whole boilerplate. It just doesn't read nor write nicely inlined in a line. Therefore this RFC to make code more legible and writeable.

Proposal

This RFC proposes the introduction of the ~> operator.

The ~> operator defines a shorthand Closure which automatically use()'s all the used compiled variables (means: variable variables, compact() etc. won't be imported from defining call frame, only normally defined $variables).

Concrete syntax is (~> is right associative with highest possible associativity):

  ( parameter_list ) ~> expression
| ( parameter_list ) ~> { statements }
/* return by reference */
| &( parameter_list ) ~> expression
| &( parameter_list ) ~> { statements }
/* shorthand form for just one parameter */
| $variable ~> expression
| $variable ~> { statements }

When a bare expression is used as second parameter, its result will be the return value of the Closure.

Examples

Partial application

function partialAdd() {
    return $left ~> $right ~> $left + $right;
}
 
/* Just to compare to the old equivalent */
function partialAdd() {
    return function($left) {
        return function($right) use ($left) {
            return $left + $right;
        }
    }
}
/* Thanks to Levi Morrison for that example */
function reduce(callable $fn) {
    return $initial ~> $input ~> {
        $accumulator = $initial;
        foreach ($input as $value) {
            $accumulator = $fn($accumulator, $value);
        }
        return $accumulator;
    };
}
 
/* Compared to */
function reduce(callable $fn) {
    return function($initial) use ($fn) {
        return function ($input) use ($fn, $initial) {
            $accumulator = $initial;
            foreach ($input as $value) {
                $accumulator = $fn($accumulator, $value);
            }
            return $accumulator;
        };
    };
}

Quick applications to arrays

/* Get a range from 2 to 10 with increment 2 */
$array = array_map($x ~> $x * 2, range(1, 5));
 
/* Compared to */
foreach (range(1, 5) as $x) {
    $array[] = $x * 2;
}
/* or */
$array = array_map(function($x) { return $x * 2; }, range(1, 5));
/* Let $array be an array filled with objects having property val. Sort them in reverse by that property. */
usort($array, ($a, $b) ~> -($a->val <=> $b->val));
 
/* Compared to */
usort($array, function($a, $b) { return -($a->val <=> $b->val); });
/* ... which will be probably multilined in a lot of places... */
usort($array, function($a, $b) {
    return -($a->val <=> $b->val);
});

General thoughts

Do we really need this?

Ultimately, it does not add any additional possibilities which weren't already possible.

But it prevents us from having to write too much boilerplate, always write use ($shit, $load, $of, $variables). In addition it saves the function and return keywords, which are not always helpful in circumstances where we just want a quick one liner to manipulate a structure or value.

Aside from that, it encourages (or makes it at least much tedious task) functional code and partial applications (see the examples), which may be a powerful tool the language shouldn't prevent.

Why ~> ?

Hack has ==>, so, why then ~>?

~> has the advantage of being shorter and it doesn't look like a =>.

That's why this RFC proposes to use ~>.

Backward Incompatible Changes

This RFC doesn't affect backwards compatibility.

Proposed PHP Version(s)

Next PHP 7.x; actually 7.1.

Future Scope

This RFC _does not_ propose shorthand methods like

class Foo {
    private $bar:
 
    getBar ~> $this->bar;
    setBar($bar) ~> $this->bar = $bar;
}

Proposed Voting Choices

This RFC is a language change and as such needs a 2/3 majority.

Patches and Tests

rfc/short_closures.1430444679.txt.gz · Last modified: 2017/09/22 13:28 (external edit)