On Thu, Apr 13, 2023, at 3:04 PM, Zoltán Fekete wrote:
> Hey guys!
>
>> On 13. Apr 2023, at 16:28, Robert Landers <landers.rob...@gmail.com> wrote:
>> 
>> I'd be down for implementing this in a heartbeat if we
>> 
>> $a = Closure::fromCallable(static fn () => $this->getId());
>> $b = Closure::bindMany($items); // executes `bind` on each item in the
>> array, returning an array of closures
>> foreach($b as $callback) {
>> $callback();
>> }
>
> Personally I find it a bit inconvenient, and also: won’t in this case 
> all the closure instance be created so space allocated for them?
>
>> or something like that. My biggest thing is that there's no real way
>> to save much on typing this out. Unless you are doing something fairly
>> exotic, you only save a few characters. That's why I said its a lot of
>> work for not much benefit. I could be totally wrong though because I,
>> personally, do run into wanting this feature several times a year.
>
> I can only tell my opinion as I also came across the same case / 
> problem. But what if I do the following:
>
> ```
> $items = [new Verification(“1”), new Verification(“2”))];
>
> $ids = array_map(NotVerification::getId(…), $items); // ofc I did that 
> so my fault but not allowing something to be done… I think it’s half 
> win. But it’s very misleading 
> ```
>
> Additionally: if I don’t have the class imported and don’t even need 
> it, than it has to be. 
>
> Essentially what we only need in the first parameter is the method name 
> that should be called. 
>
> I cannot really assess how big of a hassle it would be, but what I 
> personally think that it look nice is something like this: 
>
> ```
> class Verification
> {
>    public function __construct(private string $id) {}
>
>    public function getId(): string
>    {
>        return $this->id;
>    }
>
>    public static function getIdAbs(self $instance) {
>        return abs($instance->id);
>    }
> }
>
> $items = [new Verification(“1”), new Verification(“2”))];
>
> array_map($$->getId(…), $items);
>
> array_map($$::getIdAbs(…), $items);
> ```
>
> This way the class does not have to be imported. Later one might be 
> able to add additional parameters even.
>
> ```
> class Verification
> {
>    // […]
>
>    public static function getIdAbs(self $instance, array $idMap) {
>        // do something with the $idMap
>        return abs($instance->id);
>    }
> }
>
> // […]
>
> array_map($$::getIdAbs(…, $idMap), $items);
>
> ```
>
> I know this might be a little more exotic. But it is very straight 
> forward for static analysis tools. And no import has to be done for 
> classes. 

I believe the fancy academic name for what we're discussing here is "lenses", 
and I agree that they'd be very useful.  I currently use a user-space wrapper 
like so:

function prop(string $prop): \Closure
{
    return static fn (object $o): mixed => $o->$prop;
}

function method(string $method, ...$args): \Closure
{
    return static fn (object $o): mixed => $o->$method(...$args);
}

Which lets me do this:

$parentNames = pipe($vals,
  amap(method('getParent')),
  amap(prop('name')),
);

But I really don't like the stringy method and property names.  The T_BLING 
(that is the only name I will allow for $$) marker has been discussed on and 
off a few times over the years, I think first in Sara's original pipes proposal 
many years ago.  I was actually going to suggest the same in this thread before 
I saw you did. :-)

More abstractly, $$ meaning "the only obvious value in context" has potential, 
but also risk, because "obvious" is not always obvious.  I do think it's an 
area to explore, though, and would definitely help with functional style code 
that relies heavily on closures.

--Larry Garfield

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

Reply via email to