On Thu, Mar 16, 2023 at 11:26 PM Larry Garfield <la...@garfieldtech.com> wrote: > > On Thu, Mar 16, 2023, at 4:14 AM, Rowan Tommins wrote: > > On 15/03/2023 21:12, Dan Ackroyd wrote: > >> Would it be desirable to split those two things into two separate > >> RFCs, by having the first RFC not have native syntax support, but > >> instead another static method on Closure? e.g. something like: > >> > >> Closure::partial($callable, array $position_params, array > >> $named_params): Closure {} > > > > > > Hm... now we have the first-class callable syntax, making it an instance > > method on Closure would allow this: > > > > $mapFoo = array_map(...)->partial([$foo]); > > $filterFoo = array_filter(...)->partial([1 => $foo]); > > > > Which could copy over the full signature, so be equivalent to this: > > > > $mapFoo = static fn(array ...$arrays): array => array_map($foo, ...$arrays); > > $filterFoo = static fn(array $array, int $mode = 0): array => > > array_filter($array, $foo, $mode); > > > > While being a similar length to a much less rich version: > > > > $mapFoo = fn($array) => array_map($foo, $array); > > $filterFoo = fn($array) => array_filter($array, $foo); > > Fascinating! I... don't know if we considered something like that or not 3 > years ago. It's been a while. > > It's definitely not as nice as the integrated syntax, but it does have the > advantage of the implementation almost certainly being rather pedestrian in > comparison. That approach would favor left-to-right application, but not > force it, which is probably sufficient. > > As a thought experiment, if we had that syntax and functions that were > designed to be used with them, it would look like so: > > function amap(callable $c, iterable $it) { ... } > function implode(string $sep, iterable $it) { ... } > function length(string $s) { ... } > > $arr = [1, 2, 3]; > > $a2 = amap(...)->partial(chr(...))($arr); > > $str = implode(...)->partial(',')($a2); > > Or, if combined with pipes: > > $size = $arr > |> amap(...)->partial(chr(...)) > |> implode(...)->partial(',') > |> length(...); > > Which... is not terrible, especially as it doesn't preclude using higher > order functions for more control. > > We would likely want partial() to accept positional args (left to right) and > named args. And I'm more than happy to say now that the capture is only by > value, ever. > > I wonder if there's a shorter name we could use than "partial" to make it > more readable? Or perhaps an operator that applied only to closure objects? > > --Larry Garfield > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php >
Hey Larry, > We would likely want partial() to accept positional args (left to right) and > named args. I think this is already supported-ish. For example, here's a partial application in user space that seems to follow all the rules. Or at least the rules that are followed make sense. function partial(Closure $callable, ...$args): Closure { return static fn(...$fullArgs) => $callable(...[...$args, ...$fullArgs]); } https://onlinephp.io/c/9195a It only needs a bit of edge-condition handling (like when a parameter is filled, you probably shouldn't be able to override arbitrary parameters). -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php