On Thu, Apr 13, 2023, at 3:04 PM, Zoltán Fekete wrote:
> Hey guys!
>
>> On 13. Apr 2023, at 16:28, Robert Landers <[email protected]> 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