====== PHP RFC: Single-Expression functions ====== * **Version:** 1.0 * **Date:** 2025-05-22 * **Author:** Dmitrii Derepko, xepozzd@gmail.com * **Status:** Voting * **First Published at:** https://wiki.php.net/rfc/single-expression-functions * **Implementation:** https://github.com/php/php-src/pull/17677 ===== Introduction ===== This RFC proposes an alternative syntax for single-expression functions using the => operator instead of curly braces and explicit return statements. This syntax provides a concise way to declare simple functions without the overhead of traditional function body syntax. In PHP there are several types of functions: * traditional/classic: function ...(...) {...} * closures: function ...(...) use (...) {...} * anonymous: $var = function (...) {...} * class methods: class ... { function ...(...) {...} } * arrow(+auto captures): fn(...) => ... I'd like to discuss about class methods and classic functions. Basically, they don't capture variable from outer scope. Class methods live inside the "this" scope. There are a lot of code variants to be written in one line, but it's not acceptable with the functions. One-liner is accepted with arrow function (fn () => ...), but methods cannot be written with "fn" declaration instead of "function", as long as classic functions. ===== Proposal ===== This RFC introduces a shorthand syntax for functions that consist of a single return statement. The proposed syntax uses the => operator to denote that the function directly returns the result of the expression. //*Shorthand syntax does not affect how capturing works.//* ==== Reasoning ==== Modern codebases typically contain numerous entities, models, forms, data transfer objects (DTOs), and value objects (VOs) with many getter and setter methods. These methods are usually simple one-liners that create significant cognitive overhead with minimal functional value. Concise syntax makes it easier to associate function names with their return values, reducing mental parsing overhead. Pipe (https://wiki.php.net/rfc/pipe-operator-v3) and Partial Function Application https://wiki.php.net/rfc/partial_function_application_v2 develop ideology of functional programming and boost one-liners. ==== PSR ==== PSR-compliant syntax requires multi-line formatting: function getName() { return "Name"; } Even compact syntax contains redundant elements: function getName() { return "Name"; } ==== Cognitive Processing Analysis ==== When reading traditional function syntax, developers mentally process: function getName() { return "Name"; } The brain performs this parsing: * function - skip (boilerplate) * getName - identify function purpose * () - note no parameters * { - skip (boilerplate) * return - skip (expected keyword) * "Name" - identify return value * ; - skip (boilerplate) * } - skip (boilerplate) Effectively, the brain extracts: getName() "Name" This syntax directly represents the mental model: function maps to value, making the code more readable and reducing the cognitive load required to understand simple getter/setter methods. Unfortunately, it's not acceptable by PHP, so there should be a delimiter, e.g. =>, which is used in arrow functions. Plus functionality scope keyword, meaning "function starts". function getName() => "Name" ==== Syntax ==== function functionName(parameters): returnType => expression; This is functionally equivalent to: function functionName(parameters): returnType { return expression; } ==== Examples ==== Basic function: // Short syntax function getVersion(): int => 1; // Equivalent traditional syntax function getVersion(): int { return 1; } Function with parameters: // Short syntax function add(int $a, int $b): int => $a + $b; // Equivalent traditional syntax function add(int $a, int $b): int { return $a + $b; } Class methods: class Calculator { // Short syntax public function multiply(int $a, int $b): int => $a * $b; // Equivalent traditional syntax public function divide(int $a, int $b): float { return $a / $b; } } Proxy classes: class Proxy { private $decorated; public function doA() => $this->decorated->doA(); public function doB() => $this->decorated->doB(); } Data Models classes: class User { private $name; private $age; private $username; public function getAge() => $this->age; public function setAge($value) => $this->age = $value; public function getName() => $this->username; public function setName($value) => $this->name = $value; public function getUsername() => $this->username; public function setUsername($value) => $this->username = $value; } It should be possibly done with native property getter/setters, but such methods have different purpose compared to getters/setters. E.g. mind of UserInterface. ===== Backward Incompatible Changes ===== This change introduces no breaking changes. The proposed syntax would currently result in a parse error, making it safe to implement. ===== Proposed PHP Version(s) ===== PHP 8.5 ===== RFC Impact ===== ==== To SAPIs ==== The implementation is purely lexical—during parsing, the short syntax is transformed into the equivalent traditional syntax before further processing. This ensures no impact to SAPIs. ==== To Existing Extensions ==== Nope. ==== To Opcache ==== Implementation does compile-time changes that do not affect Opcache. ==== New Constants ==== Nope. ==== php.ini Defaults ==== Nope. ===== Open Issues ===== Make sure there are no open issues when the vote starts! ===== Unaffected PHP Functionality ===== Parent scope won't be captured as arrow functions do. Current RFC do lexer/parser modification allows to shorten typical code. ===== Future Scope ===== This section details areas where the feature might be improved in future, but that are not currently proposed in this RFC. ===== Proposed Voting Choices ===== Single voting widget that requires 2/3rd majority. * Yes * No ===== Patches and Tests ===== Links to any external patches and tests go here. If there is no patch, make it clear who will create a patch, or whether a volunteer to help with implementation is needed. Make it clear if the patch is intended to be the final patch, or is just a prototype. For changes affecting the core language, you should also provide a patch for the language specification. ===== Implementation ===== * [[https://github.com/php/php-src/pull/17677|Pull Request / php-src]] ===== References ===== * [[rfc:short-functions|Original Short Functions RFC]] * [[rfc:arrow_functions_v2|Arrow Functions RFC]] * [[rfc:pipe-operator-v3|Pipe Operator RFC]] * [[rfc:clone_with_v2|Clone RFC]] * [[https://kotlinlang.org/docs/functions.html#single-expression-functions|Single-expression functions in Kotlin]] ===== Rejected Features ===== Keep this updated with features that were discussed on the mail lists.