On Tue, Oct 20, 2020 at 8:20 PM Larry Garfield <la...@garfieldtech.com>
wrote:

> A while back, Nikita mentioned that it should now be easy to offer an
> abbreviated syntax for functions that are just a single expression.  I
> decided to take a crack at it and it turns out he was right.  I thus offer
> this RFC:
>
> https://wiki.php.net/rfc/short-functions
>
> Hopefully I made a decent enough case for it.  It's entirely a convenience
> factor, but I think for many OOP cases (getter methods and factored out
> operations) and functional cases (where functions should generally be a
> single expression conceptually) it does make the code nicer, more compact,
> and more readable.
>
> *dons flame retardant suit*
>

Overall, I do not like this proposal. I can see the appeal, and I can also
see a (rather weak) consistency argument for it, but ultimately I think
this will do more harm than good. It introduces a second way to write the
same thing, without providing a major saving in brevity. You might try to
argue the same about arrow functions, but I think the relative difference
is much more significant there.

If we take a class like this:

class X {
    public function getFoo(): int {
        return $this->foo;
    }

    public function setFoo(int $value): void {
        $this->foo = $value;
    }

    public function getBar(): int {
        return $this->bar;
    }

    public function setBar(int $value): void {
        $this->bar = $value:
    }
}

And convert it to the proposed syntax:

class X {
    public function getFoo(): int => $this->foo;

    public function setFoo(int $value): void {
        $this->foo = $value;
    }

    public function getBar(): int => $this->bar;

    public function setBar(int $value): void {
        $this->bar = $value;
    }
}

I don't think we've managed to save much screen real estate here, but we
did make the code harder to scan: In practice you will always end up mixing
the => and the {} notations, which makes it harder to pick out the function
bodies.

Now, we *could* make this more compact by writing it like this (and this
would be a significant saving):

class X {
    public function getFoo(): int => $this->foo;
    public function setFoo(int $value): int => $this->foo = $value;
    public function getBar(): int => $this->bar;
    public function setBar(int $value): int => $this->bar = $value;
}

Note that this is not the same: The setters now return the value they're
setting. You wouldn't ever do this if you used the long-hand notation, but
I can bet you that this is going to become something people routinely do
with this syntax, because it is the path of least resistance and avoids the
awkward syntax mix for getters and setters.

Now, in my first example I cheated: I used sane code formatting instead of
following PHP-FIGs recommendations (swear words omitted here). If we were
writing C++ code, which has different baseline expectations on what
acceptable formatting is, this code might have been written compactly as:

class X {
    public function getFoo(): int { return $this->foo; }
    public function setFoo(int $value): void { $this->foo = $value; }
    public function getBar(): int { return $this->bar; }
    public function setBar(int $value): void { $this->bar = $value; }
}

You'll note that this looks very similar to my last example -- with the
difference that it does not butcher the return value of the setters. Which
really goes to show that this is not a language problem, but a problem with
an unnecessarily verbose coding style guide. If you think that this kind of
concise notation is valuable, then I think the style guide should be the
first point of attack.

I think the most concerning example in the RFC is this one:

function pick_one(int $a) => match($a) {
    1 => 'One',
    2 => 'Two',
    3 => 'Three',
    default => 'More',
};

With match, the actual implementation of the function may be quite large,
even though it is only a single expression. In this case the (relative)
saving is particularly small, and the question of which form you should be
using becomes more prominent. I personally wouldn't want to see that code,
but that would require drawing a line regarding which types of expressions
are acceptable to use with this syntax and which aren't.

I also dislike the somewhat subtle requirement for a trailing semicolon
after the closing brace in this case -- it makes sense for sure, but it
looks wrong at a glance, because it's not immediately apparent that this is
not a function block, but a match block.

Regards,
Nikita

Reply via email to