Created
November 11, 2016 15:24
-
-
Save i-am-tom/6c2ca614dbc7b366c3815107b6207e59 to your computer and use it in GitHub Desktop.
A little tale to help the arrow syntax RFC along.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// == Arrow functions - A Love Story == | |
// Arrow functions are wonderful for a variety of reasons, and below are some | |
// of my favourites. Hopefully, these will provide some sort of support for | |
// the RFC. Note that none of these have been tested, though... | |
// First up: arrow functions for clear and succinct code. The ability to | |
// create lambdas with relatively little boilerplate will most obviously | |
// and primarily benefit users of callback-accepting functions. | |
// We can write tidy ways to do traversals: | |
$tree = ['a' => ['b' => ['YAY']]]; | |
$result = array_reduce(['a', 'b', 0], ($t, $k) => $t[$k], $tree); | |
// This computes a dynamic average: | |
array_reduce(range(0, 10), ($x, $y) => (3 * $x + $y) / 4, 0); | |
// And this one converts 0 - 25 to A - Z: | |
array_map($x => chr($x + 65), range(0, 25)); | |
// Reverse sort with fancy PHP7: | |
usort($dictionary, ($a, $b) => strlen($b) <=> strlen($a)); | |
// Secondly: lexical scope access. It's a common pitfall when introducing | |
// PHP to developers from other languages, as the "use" mechanism for copying | |
// variables into a closure scope is quite unique to PHP. | |
// LOADS of utility functions: | |
function pluck($k, $xs) { | |
return array_map($x => $x[$k], $xs); | |
} | |
function omit($k, $xs) { | |
return array_filter($xs, $i => $k == $i, ARRAY_FILTER_USE_KEY); | |
} | |
function every($p, $xs) { | |
return empty(array_filter($x => !$p($x), $xs)); | |
} | |
// Thirdly: partial application. https://wiki.php.net/rfc/pipe-operator would | |
// propose a "$$" operator to act as a placeholder in function calls, which is | |
// actually partial application with some syntactic sugar. Specifically, the | |
// RFC can be mimicked with some simple combinators: | |
// Function composition (a reversed "lazy chain"). | |
$compose = $f => $g => $x => $f($g($x)); | |
$map = $f => $xs => array_map($f, $xs); | |
$capitaliseEach = $map('ucfirst'); | |
// Now, we can compose these to make complex operations. | |
$process = $compose($map('ucfirst'))($map('strrev')); | |
// We can now use some functor laws to optimise this.... | |
$process = $map($compose('ucfirst')('strrev')); | |
// There are an awful lot of optimisations that can be made when functions can | |
// be partially applied. Note that this is already possible in PHP, but it's | |
// rather ugly: | |
$compose = function ($f) { | |
return function ($g) use ($f) { | |
return function ($x) use ($f, $g) { | |
return $f($g($x)); | |
}; | |
}; | |
} | |
// Having short array syntax has made this sort of code very popular within the | |
// JS community. Even if you don't go "fully functional", these are still usable: | |
$pow = $x => $y => pow($x, $y); | |
array_map($pow(2), range(0, 10)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment