> Le 28 nov. 2023 à 00:59, Sergii Shymko <ser...@shymko.net> a écrit :
> 
> Hi,
> 
> Wanted to bring up an inconsistent behavior of callable arguments compared to 
> arguments of other types.
> Callable argument cannot have a default value (tested string or array types - 
> both are not permitted).
> The same exact value works perfectly fine when passed dynamically, it just 
> cannot be specified as a default.
> The workaround is to remove the type annotation which is obviously 
> undesirable.
> 
> Here’s an example:
> declare(strict_types=1);
> function test(callable $idGenerator = 'session_create_id') {
>    $id = $idGenerator();
>    // ...
> }
> 
> The function/method declaration above produces the following error on all PHP 
> versions:
> Fatal error: Cannot use string as default value for parameter $idGenerator of 
> type callable in /tmp/preview on line 4
> 
> Note that the exact same string argument can be passed without any issue:
> function test(callable $idGenerator) {…}
> test('session_create_id’);
> 
> Is there a specific architectural limitation causing this that's 
> hard/impossible to overcome?
> 
> I’m aware that class properties cannot be annotated with callable - another 
> unfortunate limitation.
> Callable is not a real type like other primitive types which causes all these 
> inconsistencies, correct?
> Callable properties (separate topic) may be a challenge, but can at least 
> argument defaults be supported?
> 
> Regards,
> Sergii Shymko


Hi Sergii,

The big problem with the `callable` type, is that it can be check only at 
runtime. For instance:

```php
function foo(callable $x) { }

foo('strlen'); // ok
foo('i_dont_exist'); // throws a TypeError
```

Another complication, is that a value of the form `[ $class, 
$protected_or_private_method ]` may or may not be callable depending on whether 
the method is visible from the current scope.

In other words, contrarily to all other types, `callable` depends both on 
runtime state and on context.

Therefore, an argument of type `callable` cannot have a default value, because 
it is not known in advance whether the default value will be valid when used.

For the case of class properties, see  
https://wiki.php.net/rfc/typed_properties_v2#supported_types

—Claude


Reply via email to