> On 11 Aug 2022, at 07:36, Paul Crovella <paul.crove...@gmail.com> wrote:
> 
> This isn't impossible. There's nothing stopping an IDE from seeing 
> `$collection->` and suggesting/completing that with `map($collection, ` - 
> they just don't right now. Offhand I don't see why this would be more 
> difficult for them to implement than support for extension methods. As a 
> bonus it'd work with existing functions.

What’s stopping them is that those functions aren’t methods. It’d be strange 
for `$collection->m` to auto-complete to `map($collection, `. Even more strange 
would be the case where you’re trying to auto-complete on a big multiline 
expression. 

Besides, I believe working with existing functions is more of a problem than a 
bonus - because of the naming. You’d have to clutter your code with `array_map` 
calls, even though it could easily be shortened to `map`.


> On 11 Aug 2022, at 07:36, Paul Crovella <paul.crove...@gmail.com> wrote:
> 
> In short every ugly example has a fine, easy-to-read way of writing it now in 
> existing code. A useful readability comparison would pit the new feature 
> against the best looking version of example code you can come up with rather 
> than the worst. Without that you're not really demonstrating improvement.

That’s just a concept. I’d love to bring a lot more examples in an RFC if 
there’s more positive than negative feedback. Again, I’m more looking for 
feedback than trying to convince someone, but I’ll showcase a couple real 
comparisons for some context:

Compere these (copied from real world project/public composer packages):
```php
$className = Str::studly(implode('_', array_slice(explode('_', 
$file->getName()), 4)));
// vs
$className = $file->getName()->explode(‘_’)->slice(4)->implode(‘_’)->studly();

array_map(fn (string $item) => trim(mb_strtolower(strip_tags($item))), 
trans('contacts::tenants.gender_types’));
// vs
trans('contacts::tenants.gender_types’)->map(fn (string $item) => 
$item->stripTags()->lower()->trim());

array_merge($oldResponse, array_map(fn (Response $v) => 
Arr::except($v->toArray(), 'message'), $newResponse))
// vs
$oldResponse->merge($newResponse->map(fn (Response $v) => 
$v->toArray()->except(‘message')))
```

All these changes lead to a lower cognitive load, because:
 - you aren’t dealing with lots of nested parenthesis
 - you aren’t trying to read expressions “inside-out”
 - you aren’t messing with not-so-useful prefixes like `Arr::`, `array`, `str`

You could argue the problem is that all of these are single-liners, so here are 
the same examples, but multiline formatted:

```php
$className = Str::studly(
    implode(
        '_’, 
        array_slice(
            explode(
                '_’,
                $file->getName()
            ), 
            4
        )
    )
);
// vs
$className = $file->getName()
    ->explode(‘_’)
    ->slice(4)
    ->implode(‘_’)
    ->studly();

array_map(
    fn (string $item) => trim(
        mb_strtolower(
            strip_tags($item)
        )
    ),
    trans('contacts::tenants.gender_types’)
);
// vs
trans('contacts::tenants.gender_types’)->map(
    fn (string $item) => $item
        ->stripTags()
        ->lower()
        ->trim()
);

array_merge(
    $oldResponse, 
    array_map(
        fn (Response $v) => Arr::except($v->toArray(), 'message'), 
        $newResponse
    )
)
// vs
$oldResponse->merge(
    $newResponse->map(
        fn (Response $v) => $v
            ->toArray()
            ->except(‘message’)
    )
)
```

I believe the difference is quite obvious. 

Not an argument, but one more thing to consider: if current state of things in 
PHP was “good enough”, why do library authors come up with those magic method 
trait solutions, and why we’re seeing types like `Collection` being used 
instead of `array` and `Stringable` (laravel) instead of `string`, when you 
could instead just introduce a bunch of functions?


> On 11 Aug 2022, at 07:36, Paul Crovella <paul.crove...@gmail.com> wrote:
> 
> An extension method would shift a single argument from inside parentheses to 
> the left of the function name. It just moves it. I don't see any impact here.

It doesn’t move it, it removes it. You’re technically not passing that value as 
an argument anymore anywhere in your code, your value becomes the implicit 
expression you’re working with. That becomes even more obvious when multiple 
method calls are chained and don’t need to pass it into every function call.


> On 11 Aug 2022, at 07:36, Paul Crovella <paul.crove...@gmail.com> wrote:
> 
> This is essentially making `->` the pipe operator with extra steps 
> (`extension`/`use extension`) and less utility (not working on existing 
> functions.)

Well, pipe operator is another option, but it’s got it’s downsides compared to 
extension methods:
 - it's less versatile: extension methods are required to specify a type 
they’re extending, meaning they are methods, not functions. Hence, two 
different `map` method extensions can be imported in a single file (given 
they’re for different types - say one for `Collection`, the other for `array`), 
unlike regular functions. I believe it’s common place to use both 
`Collection::map` and `array::map` in a single file, but that wouldn’t be 
possible or would require aliasing
 - it’s uglier: since it just uses functions, to avoid clashes between same 
method names, prefixes would be required

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

Reply via email to