rfc:short-functions
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
rfc:short-functions [2020/10/20 18:19] – crell | rfc:short-functions [2021/04/25 19:00] – Improve reasoning section crell | ||
---|---|---|---|
Line 3: | Line 3: | ||
* Date: 2020-10-20 | * Date: 2020-10-20 | ||
* Author: Larry Garfield (larry@garfieldtech.com) | * Author: Larry Garfield (larry@garfieldtech.com) | ||
- | * Status: | + | * Status: |
- | * First Published at: http:// | + | * First Published at: http:// |
===== Introduction ===== | ===== Introduction ===== | ||
Line 19: | Line 19: | ||
function add(int $a, int $b): int | function add(int $a, int $b): int | ||
{ | { | ||
- | return $a + b; | + | return $a + $b; |
} | } | ||
</ | </ | ||
Line 48: | Line 48: | ||
Functions are simpler than lambdas, as there is no need for closing over variables contextually. | Functions are simpler than lambdas, as there is no need for closing over variables contextually. | ||
+ | ==== Consistency with closure syntax ==== | ||
+ | |||
+ | This RFC is designed to complement the [[rfc: | ||
+ | |||
+ | * The '' | ||
+ | * '' | ||
+ | * The '' | ||
+ | * The '' | ||
+ | * A function with a name is declared globally at compile time. A function without a name is declared locally as a closure at runtime. | ||
+ | |||
+ | These rules are easily recognizable and learnable by developers. | ||
+ | |||
+ | (Further discussion of the possible permutations, | ||
==== Reasoning ==== | ==== Reasoning ==== | ||
- | Many functions and methods are, in practice, simple expressions. | + | Many functions and methods are, in practice, simple expressions. |
- | Expressions are becoming increasingly capable, too. match() expressions and throw expressions in PHP 8.0, plus proposals such as [[rfc: | + | Expressions are becoming increasingly capable, too. match() expressions and throw expressions in PHP 8.0, plus proposals such as [[rfc: |
- | Expression functions are also more likely to avoid mutable state. | + | The trend in PHP in recent years has been toward |
- | ==== Examples ==== | + | ==== Pure functions ==== |
+ | |||
+ | Expression functions are also more likely to be pure, and thus avoid mutable state. | ||
+ | |||
+ | <code php> | ||
+ | |||
+ | $called = 0; | ||
+ | |||
+ | function fullName(string $first, string $last): string | ||
+ | => sprintf(' | ||
+ | </ | ||
+ | |||
+ | However, such code would be readily apparent as using global mutable state, and is easily avoided. | ||
+ | |||
+ | ===== Examples | ||
Below are some examples of "long form" current code and what the short function equivalent would be. This RFC asserts that the shorter version is more concise and readable. | Below are some examples of "long form" current code and what the short function equivalent would be. This RFC asserts that the shorter version is more concise and readable. | ||
- | === Match functions === | + | ==== Match functions |
A function that encapsulates a match() expression. | A function that encapsulates a match() expression. | ||
Line 90: | Line 117: | ||
</ | </ | ||
- | === Getter methods === | + | ==== Enum methods ==== |
+ | |||
+ | In practice, most enum methods are likely to contain only a match expression, the evaluated value of which should be returned. | ||
+ | |||
+ | <code php> | ||
+ | enum Suit | ||
+ | { | ||
+ | |||
+ | case Hearts; | ||
+ | case Diamonds; | ||
+ | case Clubs; | ||
+ | case Spades; | ||
+ | |||
+ | public function color(): string => match($this) { | ||
+ | static:: | ||
+ | static:: | ||
+ | }; | ||
+ | |||
+ | vs: | ||
+ | |||
+ | public function color(): string | ||
+ | { | ||
+ | return match($this) { | ||
+ | static:: | ||
+ | static:: | ||
+ | }; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | ==== Getter methods | ||
Many classes consist primarily or almost entirely out of methods that either return a property, or some computation off of a property. | Many classes consist primarily or almost entirely out of methods that either return a property, or some computation off of a property. | ||
Line 137: | Line 195: | ||
</ | </ | ||
- | === Functional code === | + | ==== Functional code ==== |
<code php> | <code php> | ||
Line 155: | Line 213: | ||
More complex lines of short lambdas can be wrapped to a new line like this already, and it works just as well for short-functions. | More complex lines of short lambdas can be wrapped to a new line like this already, and it works just as well for short-functions. | ||
- | === Piped functions === | + | It's also useful for basic API operations that can be expressed in terms of other basic API operations: |
- | + | ||
- | The pipe operator |> is still pending in an RFC, but the feedback on it before was generally positive. | + | |
<code php> | <code php> | ||
- | function | + | function |
- | { | + | |
- | return | + | |
- | } | + | |
</ | </ | ||
- | vs. | + | ==== Conditional methods |
- | + | ||
- | <code php> | + | |
- | function doAThing(User $u) => $u | + | |
- | |> ' | + | |
- | |> ' | + | |
- | |> ' | + | |
- | |> ' | + | |
- | ; | + | |
- | </ | + | |
- | + | ||
- | Which is a really nice way to build up a pipeline through composition. | + | |
- | + | ||
- | === Conditional methods === | + | |
- | A common refactoring technique is to take a complex conditional in an if statement and move it to its own method, so it can be given a self-descriptive name. Such methods are naturally single-expression. | + | A common refactoring technique is to take a complex conditional in an if statement and move it to its own method, so it can be given a self-descriptive name. Such methods are naturally single-expression. Thus, well-factored code is likely to have a large percentage of its functions and methods be single-expression, |
<code php> | <code php> | ||
Line 196: | Line 236: | ||
} | } | ||
- | ... | + | // ... |
protected function isGroupModerator(): | protected function isGroupModerator(): | ||
=> $this-> | => $this-> | ||
- | |||
</ | </ | ||
- | === Decorating functions in live code === | + | Which is more simple and compact than a full function body. |
+ | |||
+ | ==== Decorating functions in live code ==== | ||
Often times, methods exist that are just delegating to some other method, either in the same object or a composed object. | Often times, methods exist that are just delegating to some other method, either in the same object or a composed object. | ||
Line 311: | Line 352: | ||
That can collapse to this (a bit reordered): | That can collapse to this (a bit reordered): | ||
- | |||
<code php> | <code php> | ||
Line 372: | Line 412: | ||
The => operator has de facto become the "maps to this expression" | The => operator has de facto become the "maps to this expression" | ||
- | I opted to not change | + | The use of the '' |
+ | |||
+ | ===== Related RFCs ===== | ||
+ | |||
+ | A number of other RFCs in active consideration | ||
+ | |||
+ | ==== Piped functions ==== | ||
+ | |||
+ | The [[rfc: | ||
+ | |||
+ | <code php> | ||
+ | function doAThing(User $u) | ||
+ | { | ||
+ | return $u |> ' | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | vs. | ||
+ | |||
+ | <code php> | ||
+ | function doAThing(User $u) => $u | ||
+ | |> ' | ||
+ | |> ' | ||
+ | |> ' | ||
+ | |> ' | ||
+ | ; | ||
+ | </ | ||
+ | |||
+ | Which is a really nice way to build up a pipeline through composition. | ||
+ | |||
+ | ==== clone-with ==== | ||
+ | |||
+ | Although no formal RFC has been proposed, Máté had discussed a '' | ||
+ | |||
+ | <code php> | ||
+ | class Point | ||
+ | { | ||
+ | public function __construct(private int $x, private int $y) {} | ||
+ | |||
+ | public function getX(): int => $this-> | ||
+ | public function getY(): int => $this-> | ||
+ | |||
+ | public function withX($x): static => clone($this) with {x: $x}; | ||
+ | public function withY($y): static => clone($this) with {y: $y}; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Thus making many cases of wither methods just as trivial | ||
===== Backward Incompatible Changes ===== | ===== Backward Incompatible Changes ===== | ||
Line 381: | Line 468: | ||
PHP 8.1. | PHP 8.1. | ||
- | |||
===== Open Issues ===== | ===== Open Issues ===== | ||
Line 394: | Line 480: | ||
[[https:// | [[https:// | ||
- | |||
- | Pull request for the spec still to come. | ||
===== Implementation ===== | ===== Implementation ===== |
rfc/short-functions.txt · Last modified: 2021/06/15 22:29 by ilutov