On 25/04/2021 20:25, Larry Garfield wrote:
Greetings, Internalians!

I would like to offer for your consideration another RFC, specifically syntax 
for partial function application.

https://wiki.php.net/rfc/partial_function_application


During off-list discussions, it's become clear that there are two different ways of modelling what this feature does, which is leading to a bit of misunderstanding and frustration (and some plain disagreement on which is the *better* model). At risk of getting it wrong and confusing things more, I'd like to attempt to describe the two models.


The first model is that a partial application starts with an empty signature, and adds arguments to it based on placeholders. You could picture the steps like this:

function foo(int $a, int $b, int $c) { /* whatever */ }
$partial = foo(?, ?, 42);
Step 1 - empty closure: $partial = fn() => foo();
Step 2 - 1st argument is a ? so copy that parameter from the original: $partial = fn(int $a) => foo($a); Step 3 - 2nd argument is a ? so copy from the original: $partial = fn(int $a, int $b) => foo($a, $b); Step 4 - 3rd argument is a fixed value, so don't add to signature, only to the call: fn(int $a, int $b) => foo($a, $b, 42);


The second model is that a partial application starts with a *complete* signature, and splices in the *fixed* values. The steps go more like this:

function foo(int $a, int $b, int $c) { /* whatever */ }
$partial = foo(?, ?, 42);
Step 1 - copy original signature: $partial = fn(int $a, int $b, int $c) => foo($a, $b, $c);
Step 2 - 1st argument is a ? so skip over it
Step 3 - 2nd argument is a ? so skip over it
Step 4 - 3rd argument is a fixed value, so splice a value into the signature at that location: $partial = fn(int $a, int $b, 42) => foo($a, $b, 42); Step 5 - fixed values don't actually belong on the left-hand side: $partial = fn(int $a, int $b) => foo($a, $b, 42);


For simple examples like the above, the two models are essentially equivalent, but they lead to different expectations for some features; for instance, trailing arguments and placeholders:

- In the model where you're building from empty, writing foo(42, ?, ?) to mean "copy exactly two arguments" feels natural. To say "copy all arguments", or "copy all remaining arguments", you'd then need a different syntax, like foo(42, ...) or foo(42, ??). In this model, the trailing "?" in the current proposal is magic: it changes from meaning "copy exactly one argument" to "copy all remaining arguments".

- In the model where you're splicing arguments into a full signature, foo(42, ?, ?) is pointless: the action is to splice in the 42, then "skip over" two arguments; but nothing happens *after* skipping over them, so you could just not mention them. No extra token is needed to copy all remaining arguments, because that already happened at the start. The only reason to use a trailing "?" at all is because foo(42) would just be a normal function call, and adding a redundant "skip over" marker in foo(42, ?) tells the compiler it's a partial.


Regards,

--
Rowan Tommins
[IMSoP]

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

Reply via email to