Hi, Internals!
I hope this message finds you well. I would like to respectfully propose
single-expression functions for PHP:
https://wiki.php.net/rfc/single-expression-functions
I've had extensive experience working with Kotlin, which offers a modern
approach to Java development and enables cleaner, more intuitive code.
Through this experience, I've encountered various concise syntax features,
and I believe one of them—single-expression functions—could be a valuable
addition to PHP.
I'm aware that Larry Garfield previously proposed a similar feature several
years ago, though it unfortunately didn't pass the voting stage. I would
like to respectfully suggest that using "=" instead of "=>" to separate
declaration and implementation might be a better approach.
I believe this proposal aligns well with PHP's current modernization
efforts and the ongoing initiative to simplify various language constructs.
PHP has been consistently improving developer experience through features
like property promotion, arrow functions, the nullsafe operator,
getters/setters, and other syntax enhancements. This single-expression
function syntax would be a natural continuation of this trend, further
streamlining the developer workflow and making PHP more pleasant to write.
The primary motivation is to help streamline "data classes" by eliminating
the need for "{", "return", and "}", which can sometimes account for up to
30% of the code in such classes. This improvement would be particularly
timely as it directly enhances developer experience—a key focus of PHP's
recent evolution.
I would greatly appreciate your thoughts and feedback on this proposal, and
I'm looking forward to engaging in constructive discussion with the
community.
Thank you for your time and consideration.
Dmitriy Derepko
Hi Dmitriy
I'm aware that Larry Garfield previously proposed a similar feature
several years ago, though it unfortunately didn't pass the voting stage.
I would like to respectfully suggest that using "=" instead of "=>" to
separate declaration and implementation might be a better approach.
That looks like the weakest part of the proposition because we already
have two places where inline bodies are used: the mentioned arrow
functions and property hooks
public string $foo { get => 'dynamic value'; }
No sense in introducing a new syntax for basically just another case of
inline function body.
// oneline
function handle(string $input): string = func1($input) |> func2(...)
|> func3(...) |> func4(...);
That looks like a callable assignment like you know
$f = fn ($bar) => $this->bar + $bar;
class Foo {
private $bar;
public function bar() = $f;
}
that may confuse users, another argument for =>
--
Anton
Hi Dmitriy
I'm aware that Larry Garfield previously proposed a similar feature
several years ago, though it unfortunately didn't pass the voting stage.
I would like to respectfully suggest that using "=" instead of "=>" to
separate declaration and implementation might be a better approach.
That looks like the weakest part of the proposition because we already
have two places where inline bodies are used: the mentioned arrow
functions and property hookspublic string $foo { get => 'dynamic value'; }
No sense in introducing a new syntax for basically just another case of
inline function body.// oneline
function handle(string $input): string = func1($input) |> func2(...)
|> func3(...) |> func4(...);That looks like a callable assignment like you know
$f = fn ($bar) => $this->bar + $bar;
class Foo {
private $bar;public function bar() = $f;
}
that may confuse users, another argument for =>
--
Anton
Like Anton, I believe the arguments for using => and not = are strong, as detailed in the original RFC. Other than that, I am unsurprisingly in favor of short-function syntax.
If memory serves, the main argument against last time was "it doesn't actually do anything." It's purely sugar. Which is true, but IMO also not a fully compelling argument. Constructor promotion is purely sugar, but it absolutely makes life better. The short-hooks syntax is purely sugar, but makes life better. The question is whether the QoL improvement of the sugar justifies the engine complexity + conceptual complexity (for readers) that every feature comes with.
In this case, the engine complexity is not zero, but pretty close to it. The conceptual complexity is also low, especially if using =>. It is already established to mean "evaluates to", which is exactly what is described here. So the overall cost of this change would be quite low.
While the QoL benefit is not as large as it was for constructor promotion (which was huge), I do believe it is large enough to justify the fairly low cost. Especially as we integrate more and more expression-oriented features over time (pipes, null-safe methods, match(), throwable expressions, etc), which increases the surface area where the benefits will be felt.
--Larry Garfield
Thanks for your replies.
There is no big deal for me to use =>
instead of =
. Just used to use
=
. I’ll change it then.
Thought there would be more thoughts against the RFC, but the voting will
show these votes.
Could someone help me with the RFC process? Should I open the vote?
Dmitrii Derepko.
@xepozz
Hi
Could someone help me with the RFC process? Should I open the vote?
Please find https://wiki.php.net/rfc/howto for an explanation of the
process.
An RFC needs at least two weeks of discussion, depending on the
complexity of the RFC it should probably be longer to give everyone
sufficient time to read the RFC and think it through.
Personally I did not yet have time to carefully read and understand the
RFC to provide proper feedback.
Best regards
Tim Düsterhus
Thanks for your replies.
There is no big deal for me to use
=>
instead of=
. Just used to
use=
. I’ll change it then.Thought there would be more thoughts against the RFC, but the voting
will show these votes.
Could someone help me with the RFC process? Should I open the vote?
As Tim said, it needs at least a 2 week discussion period. It's also good practice to give it a few days after the last meaningful change, and announce an intent to open the vote a day or three in advance.
Did I miss it or did I not see a PR linked from the RFC? While technically having an implementation is not a prerequisite of an RFC, it is strongly recommended. (Also, having written the original patch, I'm curious if you're doing it the same way I did. It also may be sensible to use the compile step rather than strictly the lexer; moving pipes from strictly lexer to a compile step was a very smart move, for instance, as it simplified a lot of the ancillary behavior around debugging and error messages.)
--Larry Garfield
As Tim said, it needs at least a 2 week discussion period.
Could you share the reference?
Did I miss it or did I not see a PR linked from the RFC? While technically
having an implementation is not a prerequisite of an RFC, it is strongly
recommended. (Also, having written the original patch, I'm curious if
you're doing it the same way I did. It also may be sensible to use the
compile step rather than strictly the lexer; moving pipes from strictly
lexer to a compile step was a very smart move, for instance, as it
simplified a lot of the ancillary behavior around debugging and error
messages.)
Here it is. I've added the link to the RFC.
It was one of my first PRs in PHP, so I did the things I only learned from
there.
Lexer still should be adjusted to accept =>
syntax.
Best regards,
Dmitrii Derepko.
@xepozz
Hi
Am 2025-05-27 09:08, schrieb Dmitry Derepko:
As Tim said, it needs at least a 2 week discussion period.
Could you share the reference?
I already did in my email: https://wiki.php.net/rfc/howto (“When
discussion ends, and a minimum period of two weeks has passed”).
Here it is. I've added the link to the RFC.
It took me a while to find the link in the “References” section, because
that's not where I expected it based on other RFCs. Overall the RFC
diverges from the RFC template quite a bit. As an example, the “RFC
Impact” section is entirely missing. The “Voting Choices” section is as
well. The “Metadata” section at the top is formatted differently for no
reason (and still indicates that the RFC is a Draft). As far as I can
tell it's also not listed in the RFC overview at
https://wiki.php.net/rfc either.
As a first-time RFC author, I would recommend you strictly following the
template and the “RFC How-To” to make sure that the RFC is complete and
follows proper process.
Best regards
Tim Düsterhus
Thanks Tim for the answer.
Your replies went to the Spam folder. I don't know why.
I'll change the template as you suggested as soon as possible.
Hi
Am 2025-05-27 09:08, schrieb Dmitry Derepko:
As Tim said, it needs at least a 2 week discussion period.
Could you share the reference?
I already did in my email: https://wiki.php.net/rfc/howto (“When
discussion ends, and a minimum period of two weeks has passed”).Here it is. I've added the link to the RFC.
It took me a while to find the link in the “References” section, because
that's not where I expected it based on other RFCs. Overall the RFC
diverges from the RFC template quite a bit. As an example, the “RFC
Impact” section is entirely missing. The “Voting Choices” section is as
well. The “Metadata” section at the top is formatted differently for no
reason (and still indicates that the RFC is a Draft). As far as I can
tell it's also not listed in the RFC overview at
https://wiki.php.net/rfc either.As a first-time RFC author, I would recommend you strictly following the
template and the “RFC How-To” to make sure that the RFC is complete and
follows proper process.Best regards
Tim Düsterhus
--
Dmitriy Derepko
I've changed the structure, followed the rfc template now.
The voting section isn't available now, because the RFC is under discussion.
Thanks Tim for the answer.
Your replies went to the Spam folder. I don't know why.
I'll change the template as you suggested as soon as possible.
Hi
Am 2025-05-27 09:08, schrieb Dmitry Derepko:
As Tim said, it needs at least a 2 week discussion period.
Could you share the reference?
I already did in my email: https://wiki.php.net/rfc/howto (“When
discussion ends, and a minimum period of two weeks has passed”).Here it is. I've added the link to the RFC.
It took me a while to find the link in the “References” section, because
that's not where I expected it based on other RFCs. Overall the RFC
diverges from the RFC template quite a bit. As an example, the “RFC
Impact” section is entirely missing. The “Voting Choices” section is as
well. The “Metadata” section at the top is formatted differently for no
reason (and still indicates that the RFC is a Draft). As far as I can
tell it's also not listed in the RFC overview at
https://wiki.php.net/rfc either.As a first-time RFC author, I would recommend you strictly following the
template and the “RFC How-To” to make sure that the RFC is complete and
follows proper process.Best regards
Tim Düsterhus--
Dmitriy Derepko
--
Best regards,
Dmitrii Derepko.
@xepozz
Hi Dmitry
Thanks for your interest in improving PHP.
In the "Single-Expression functions in other languages" section, at least the Rust and Swift examples are wrong, as such a syntax does not exist for either of them. In case you got this info from an LLM, you should always fact-check whatever an AI tells you.
Ilija
In the "Single-Expression functions in other languages" section, at
least the Rust and Swift examples are wrong, as such a syntax does not
exist for either of them. In case you got this info from an LLM, you
should always fact-check whatever an AI tells you.
Sure I did. Seems like I was confused by specifying a variable type along
with the assigned value:
Documentation
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/functions/#Using-Function-Types
docs.swift.org
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/functions/#Using-Function-Types
[image: favicon.ico]
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/functions/#Using-Function-Types
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/functions/#Using-Function-Types
var mathFunction: (Int, Int) -> Int = addTwoInts
I’ve double checked examples and removed Swift and Rust. Thanks for that.
Best regards,
Dmitrii Derepko.
@xepozz
Hi
Am 2025-05-22 11:24, schrieb Dmitry Derepko:
I hope this message finds you well. I would like to respectfully
propose
single-expression functions for PHP:
https://wiki.php.net/rfc/single-expression-functions
Thank you for updating the RFC to match the template. I've read through
it and have some comments:
In the implementation I'm seeing that $a = function() => 123;
will
also become legal (“short closures with function instead of fn”). This
is not mentioned in the RFC text. It also raises the question how that
variant will interact with variable capturing.
An AST printing test in the implementation would be useful to have. You
can do that with assert(false && new class { });
(using an anonymous
class).
I believe the reasoning given is not a fair comparison. The RFC says
that getName() "Name"
would be the relevant information, which I can
agree with. But this is not what the proposed syntax looks like. A fair
comparison would be:
function getName() { return "Name"; }
function getName() => "Name";
And when compared like this, it becomes clear that you are trading {}
for =>
and effectively only save the return
, which to me provides
little incremental value. Especially when comparing the signatures from
the Calculator example:
public function multiply(int $a, int $b): int => $a * $b;
public function multiply(int $a, int $b): int { return $a * $b; }
I also don't like how the actual implementation is pushed to the right
of the line. This makes it harder for me to scan for it. The linebreaks
that the RFC states “create cognitive overhead” guide the eye for me. So
perhaps we should also compare:
public function multiply(int $a, int $b): int
=> $a * $b;
public function multiply(int $a, int $b): int {
return $a * $b;
}
So basically the only thing we gain is the removal of a keyword in some
situations. When trying to extend the logic in a function to more than
one expression (which is not unlikely for methods), I would be forced to
make multiple “boilerplate” changes instead of just adding my logic,
effectively undoing any benefit the syntax might've provided.
Thus I'm very skeptical that the RFC provides sufficient value to
justify the impact on the ecosystem (e.g. IDEs, static analyzers,
documentation, confusion regarding another closure syntax, …).
Best regards
Tim Düsterhus