Re: Explicit callee defaults

From: Date: Sat, 27 Jul 2024 09:41:30 +0000
Subject: Re: Explicit callee defaults
References: 1  Groups: php.internals 
Request: Send a blank email to [email protected] to get a copy of this message


On Fri, Jul 26, 2024, at 23:54, Bilge wrote:
> Hi Internals,
> 
> New RFC idea just dropped. When writing a function, we can specify defaults for its parameters,
> and when calling a function we can leverage those defaults *implicitly* by not specifying those
> arguments or by "jumping over" some of them using named parameters. However, we cannot
> *explicitly* use the defaults. But why would we want to?
> 
> Sometimes we want to effectively *inherit* the defaults of a function we're essentially
> just proxying. One way to do that is copy and paste the entire method signature, but if the defaults
> of the proxied method change, we're now overriding them with our own, which is not what we
> wanted to do. It is possible, in a roundabout way, to avoid specifying the optional parameters by
> filtering them out (as shown in the next example). The final possibility is to use reflection and
> literally query the default value for each optional parameter, which is the most awkward and verbose
> way to inherit defaults.
> 
> Let's use a concrete example for clarity.
> 
> function query(string $sql, int $limit = PHP_INT_MAX, int $offset = 0);
> 
> 
> 
> function myQuery(string $sql, ?int $limit = null, ?int $offset = null) {
>     query(...array_filter(func_get_args(), fn ($arg) => $arg !== null));
> }
> 
> 
> In this way we are able to filter out the null arguments to inherit the callee defaults, but
> this code is quite ugly. Moreover, it makes the (sometimes invalid) assumption that we're able
> to use null for all the optional arguments.
> 
> In my new proposal for *explicit *callee defaults, it would be possible to use the
> default keyword to expressly use the default value of the callee in that argument
> position. For example, the above implementation for myQuery() could be simplified to the following.
> 
> 
> 
> function myQuery(string $sql, ?int $limit = null, ?int $offset = null) {
>     query($sql, $limit ?? default, $offset ?? default);
> }
> 
> 
> Furthermore, it would also be possible to "jump over" optional parameters *without*
> using named parameters.
> 
> json_decode($json, true, default, JSON_THROW_ON_ERROR);
> 
> This proposal is built on the assumption that it is possible to specify that PHP should only
> accept the default expression in method and function call contexts. For example, it
> would not be valid to return default from a function and substitute it that way; my
> proposal is to only permit default in literal function calling contexts. My knowledge
> of internals is insufficient (read: non-existent) to know whether or not this restriction is
> possible to implement, but if it is, I think this is a good idea. What do you think?
> 
> 
> 
> Cheers,
> Bilge
> 
> 

This seems like a case for code generation — and an RFC that provides hooks for code generation
would probably be better IMHO.

There are a couple of neat tools out there doing this and hooking into composer, like https://packagist.org/packages/olvlvl/composer-attribute-collector

There are many things that could benefit from this, such as DI containers, scanning for attributes,
generating efficient serializers/deserializers, etc. 

— Rob


Thread (11 messages)

« previous php.internals (#124640) next »