Re: First-class callable partial application

From: Date: Wed, 15 Mar 2023 10:17:04 +0000
Subject: Re: First-class callable partial application
References: 1 2 3 4 5 6 7 8 9 10 11 12  Groups: php.internals 
Request: Send a blank email to internals+get-119707@lists.php.net to get a copy of this message
On Tue, Mar 14, 2023 at 5:58 PM Larry Garfield <larry@garfieldtech.com> wrote: > > On Tue, Mar 14, 2023, at 8:50 AM, Robert Landers wrote: > > On Tue, Mar 14, 2023 at 1:57 PM Rowan Tommins <rowan.collins@gmail.com> wrote: > >> > >> On Tue, 14 Mar 2023 at 10:39, Bob Weinand <bobwei9@hotmail.com> wrote: > >> > >> > Hey Rowan, > >> > > >> > do we actually need *positional* partial application, after a ... token? > >> > > >> > Would it not be enough, to simply forbid positional arguments after a ... > >> > and just allow named arguments? These already have well defined position > >> > independent semantics. > >> > > >> > There may be some desire for a single argument placeholder later on, but > >> > this can be introduced later, separately. > >> > > >> > >> > >> Yes, named parameters would certainly be better than left-to-right only. > >> It's definitely less elegant, though, and given that PFA is largely > >> short-hand for a short closure anyway, I think conciseness is quite an > >> important aim. > >> > >> To take a couple of the above examples, and compare existing short closure, > >> fully positional PFA, and named-after-placeholder PFA: > >> > >> $isLogger = fn($object) => is_subclass_of($object, LoggerInterface::class, > >> false); > >> $isLogger = is_subclass_of(?, LoggerInterface::class, false); > >> $isLogger = is_subclass_of(..., class: LoggerInterface::class, > >> allow_string: false); > >> > >> $priceFormatter = fn(float $num) => number_format($num, 2, ',', > >> '.'); > >> $priceFormatter = number_format(?, 2, ',', '.'); > >> $priceFormatter = number_format(..., decimals: 2, decimal_separator: ',', > >> thousands_separator: '.'); > >> > >> Arguably the named param version is more explicit, but in some cases it's > >> significantly longer than manually defining a closure, whereas fully > >> positional PFA is always shorter. > >> > >> Regards, > >> -- > >> Rowan Tommins > >> [IMSoP] > > > > Something I was partial to (pun slightly intended), when thinking > > about it last summer was to put named parameters with dots following, > > like this: > > > > $isLogger = is_subclass_of(object_or_class..., LoggerInterface::class, false); > > // or, since this is a beginning/end partial, this is the same: > > $isLogger = is_subclass_of(..., LoggerInterface::class, false); > > > > $isLogger(object_or_class: $myClass); > > // or > > $isLogger($myClass); > > > > $priceFormatter = number_format(num..., 2, ',', '.'); > > > > At least, that was what I was going to propose, according to my notes. > > Looking at it 8 months later, I still kinda like it. > > For reference, in the original RFC we had the following rules: > > ``` > This RFC introduces two place holder symbols: > > The argument place holder ? means that exactly one argument is expected at this position. > The variadic place holder ... means that zero or more arguments may be supplied at this > position. > > The following rules apply to partial application: > > ... may only occur zero or one time > ... may only be followed by named arguments > named arguments must come after all place holders > named placeholders are not supported > ``` > > The reason for that was, I believe, because it was too complicated figure out the signature of > the resulting closure if named placeholders were allowed after the > ... . Optional arguments also got weird, IIRC. We went around *a > lot* on the details here before settling on the syntax we did. > > I agree that requiring all partials to used named args would be a big step down for usability. > > But again, none of this addresses the root issue that doomed the previous RFC: Any syntax that > involves a runtime determination of "is this a function call or a partial application?" is > going to involve some really tricky dancing along the critical path of all function calls. Even > though Joe's implementation had no significant performance impact (AFAIR), it still made the > code more complex and potentially harder to optimize in the future. > > So the only ways forward would be: > > 1) Find another approach in the implementation that doesn't have that problem, which may > then changes to the proposed syntax and possibility capabilities. (I had suggested some prefix on > the call to indicate that it's a partial and not a call, like %foo(1, ?, 3, ...) or something.) > 2) The voter base shifts and/or changes its mind and decides that the extra complexity is worth > it. > > Redoing the syntax bikeshedding from 3 years ago (dear god, it's been 3 years?) before one > of those two is answered is not productive. New engine approach first, then syntax based on what > that approach allows. > > --Larry Garfield > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php > Hey Larry, > Redoing the syntax bikeshedding from 3 years ago (dear god, it's been 3 years?) before one > of those two is answered is not productive. New engine approach first, then syntax based on what > that approach allows. This is why my approach was one of syntax sugar. Sure, it would make the call stack weird during exceptions, but all-in-all, not much changes from an engine standpoint. Most of the changes were to the grammar IIRC. I'll hop on my old computer this weekend and submit a PR to make the discussion easier.

« previous php.internals (#119707) next »