# PHP RFC: Single-Expression functions - **Version**: 1.0 - **Date**: 2025-05-22 - **Author**: Dmitrii Derepko - **Status**: Draft - **Target Version**: PHP 8.5 ## 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. ## 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. ### 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. #### Current Syntax Problems PSR-compliant syntax requires multi-line formatting: ```php function getName() { return "Name"; } ``` Even compact syntax contains redundant elements: ```php function getName() { return "Name"; } ``` #### Cognitive Processing Analysis When reading traditional function syntax, developers mentally process: ```php 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: ```php 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. ### Syntax ```php function functionName(parameters): returnType = expression; ``` This is functionally equivalent to: ```php function functionName(parameters): returnType { return expression; } ``` ### Examples Basic function: ```php // Short syntax function getVersion(): int = 1; // Equivalent traditional syntax function getVersion(): int { return 1; } ``` Function with parameters: ```php // 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: ```php 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; } } ``` ## Rationale ### Distinction from Arrow Functions This proposal deliberately uses `=` instead of `=>` to avoid confusion with existing arrow function syntax (`fn() => expression`). The key differences are: - Scope: Short functions with `=` are regular named functions with global scope - Capture: No variable capture from parent scope (unlike `fn`) - Syntax: Uses `function` keyword, not `fn` - Purpose: Syntactic sugar for simple return statements ### Benefits 1. Reduced verbosity for simple functions 2. Improved readability for single-expression functions 3. Consistency with modern language trends toward concise syntax 4. No performance impact - purely lexical transformation 5. Visual clarity - removes 8 symbols, 1 line instead of 4 6. Faster comprehension of function purpose and return value 7. Consistent with mathematical notation where f(x) = expression 8. Maintains clarity while eliminating redundancy ### Use Cases Getter methods: ```php class User { public function __construct( private string $name, private string $email ) {} public function getName(): string = $this->name; public function getEmail(): string = $this->email; public function getDisplayName(): string = ucfirst($this->name); } ``` Simple calculations: ```php function calculateTax(float $amount): float = $amount * 0.18; function isEven(int $number): bool = $number % 2 === 0; function formatCurrency(float $amount): string = '$' . number_format($amount, 2); ``` Delegation methods: ```php class Service { public function __construct(private Repository $repo) {} public function findById(int $id): ?Entity = $this->repo->find($id); public function count(): int = $this->repo->count(); } ``` ## Technical Implementation The implementation is purely lexical—during parsing, the short syntax is transformed into the equivalent traditional syntax before further processing. This ensures: - No runtime performance impact - Full compatibility with existing reflection APIs - Identical behavior to traditional function declarations ## Backward Compatibility This change introduces no breaking changes. The proposed syntax would currently result in a parse error, making it safe to implement. ## Alternative Syntax Considered ### Using => operator The original [Short Functions RFC](https://wiki.php.net/rfc/short-functions) proposed using `=>`, but this creates confusion with arrow functions: ```php // Confusing - looks like an arrow function function add(int $a, int $b): int => $a + $b; // Clear distinction function add(int $a, int $b): int = $a + $b; ``` ### Pipe Operator usage ```php // multiline function handle(string $input): string = func1($input) |> func2(...) |> func3(...) |> func4(...) ; // oneline function handle(string $input): string = func1($input) |> func2(...) |> func3(...) |> func4(...); ``` ### Clone ```php class Point { public function __construct(private int $x, private int $y) {} public function withX($x): static => clone($this, ["x" => $x]); public function withY($y): static => clone($this, ["y" => $y]); } ``` ```php class Point { public function __construct(private int $x, private int $y) {} public function withX($x): static { return clone($this, ["x" => $x]); } public function withY($y): static { return clone($this, ["y" => $y]); } } ``` ### Single-Expression functions in other languages #### Kotlin ```kotlin fun add(a: Int, b: Int): Int = a + b fun getVersion() = 1 fun isEven(n: Int) = n % 2 == 0 ``` #### Scala ```scala def add(a: Int, b: Int): Int = a + b def getVersion: Int = 1 def square(x: Int) = x * x ``` #### F# ```fsharp let add a b = a + b let getVersion () = 1 let isPositive x = x > 0 ``` #### Rust ```rust fn add(a: i32, b: i32) -> i32 = a + b; fn get_version() -> i32 = 1; fn add(a: i32, b: i32) -> i32 { a + b } ``` #### Haskel ```haskel add :: Int -> Int -> Int add a b = a + b getVersion :: Int getVersion = 1 ``` #### Swift ```swift func add(_ a: Int, _ b: Int) -> Int = a + b func getVersion() -> Int = 1 ``` #### C# ```csharp public int Add(int a, int b) => a + b; public string FullName => $"{FirstName} {LastName}"; public int GetVersion() => 1; ``` #### Dart ```dart int add(int a, int b) => a + b; String get fullName => '$firstName $lastName'; ``` #### Elixir ```elixir def add(a, b), do: a + b def get_version, do: 1 ``` #### Javascript/Typescript (named closures) ```javascript const add = (a, b) => a + b; const getVersion = () => 1; ``` ## Limitations 1. Single expression only - multi-statement functions require traditional syntax 2. No variable assignments - cannot declare variables within the expression 3. No control structures - if/else must use ternary operator ## Future Scope This feature could potentially be extended to: - Interface method declarations with default implementations - Omitting the `function` keyword to declare a function – class member ## References - [Original Short Functions RFC](https://wiki.php.net/rfc/short-functions) - [Arrow Functions RFC](https://wiki.php.net/rfc/arrow_functions_v2) - [Pipe Operator RFC](https://wiki.php.net/rfc/pipe-operator-v3) - [Clone RFC](https://wiki.php.net/rfc/clone_with_v2) - [Single-expression functions in Kotlin](https://kotlinlang.org/docs/functions.html#single-expression-functions)