Bringing this thread to the main one

On Sun, 24 Apr 2016 06:27:39 +0300, Mathieu Rochette <math...@rochette.cc> wrote:

I've seen someone mentioning variadics so I made a few small tests, I
think those two should work (they currently don't):

https://3v4l.org/eZgR9/rfc#rfc-callable_typehint
https://3v4l.org/N7i0u/rfc#rfc-callable_typehint

and this one should not:

https://3v4l.org/fcRlT/rfc#rfc-callable_typehint

Hey,

You're right, this code should be valid

    function foo(callable() $a) { $a(); }
    foo(function (...$args) {});

But it gets into the same problems like optional params when it is typed

    function foo(callable() $a) { $a(123); }
    foo(function (A ...$args) {});

Now to the question why would `foo()` call `$a` with additional arguments
even though it assumes `$a` is of type `callable()`? Well at first
because it can - this is enough for it to be not type safe :P
Long answer is: in the real life there will definitely be cases where
this would allow users to shoot their feet, take this example:

function map(/* array | Traversable */ $collection, callable($value, $index) $mapper) {
        $out = [];
        foreach ($collection as $index => $value) {
            $out[] = $mapper($value, $index);
        }
        return $out;
    }
...
    function renderPost(Post $p, bool $asAdmin = false) {
return render("post_template", ["post" => $p, "asAdmin" => $asAdmin]);
    }
...
    $renderedPosts = map($posts, "renderPost");
// here developer would get fatal at the line `$out[] = $mapper($value, $index);`
    // if optional parameters were supported
// Without them though, he gets TypeError when he passes "renderPost" to map()
    // And it says nicely what exactly he has done wrong

Even now though, he could get into this situation if `$asAdmin`
parameter was not properly typed, but that would be on him as
he'd need to voluntarily drop those types for which I don't see
a reason to do so.

Now talking about an immediate solution to hypothetical problem we are facing there is an easy solution - if you have a functional library, you'll probably
have there `partial_any` function of some kind (ex. [0]),
so what you could instead do is:

$renderedPosts = map($posts, f\partial_any("renderPost", f\placeholder(), true));

This would always pass `true` to a second parameter, but leave the first one.

[0] https://github.com/lstrojny/functional-php/blob/master/docs/02-partial-application.md#partial_any

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

Reply via email to