Idea: Pure Functions in PHP

From: Date: Fri, 25 Sep 2026 19:58:40 +0000
Subject: Idea: Pure Functions in PHP
Groups: php.internals 
Request: Send a blank email to internals+get-132643@lists.php.net to get a copy of this message
Hello, internals, I have been thinking about an RFC idea. The subject is pure functions. First, let us define, for formality, what pure functions are. Straight from Wikipedia, a pure function is a function that follows the following properties: - the function return values are identical for identical arguments. - the function has no side effects (no mutation of non-local variables, mutable reference arguments or input/output streams). In PHP, there is no formal distinction in the language between pure and impure functions. The proposal would be a new Pure attribute that, for example, when applied to the function foo, would require it to be pure. Therefore, the function foo: - could not call functions and methods that do not have the Pure attribute, such as those that generate I/O side effects, such as file_get_contents, file_put_contents, print. - could not access any external values, such as: - could not access superglobal variables, $_SESSION, $_REQUEST, $_GET, $_POST etc. - could not access variables from its class - if it is a method - such as $this->val, self::$val, static::$val. - could not access static variables from other classes, such as OtherClass::$val. - etc. --- With the new attribute, an example of a valid pure function would be: ```php #[Pure] function my_array_first(array $array, mixed $fallback = null): mixed { return $array ? $array[array_key_first($array)] : $fallback; } echo my_array_first([], 11); // 11 ``` Some examples of invalid pure functions (which would cause Fatal errors) would be: ```php #[Pure] function random_number(int $a): int { return random_int(10, 20) + $a; } echo random_number(10); // Fatal error: pure function random_number() calls impure function random_int(). ``` ```php class Ha { private int $a = 1; #[Pure] public function getA(): int { return $this->a; } } new Ha()->getA(); // Fatal error: pure method Ha::getA() accesses $this. ``` ```php #[Pure] function request_method(): string { return $_SERVER['REQUEST_METHOD']; } echo request_method(); // Fatal error: pure function request_method() accesses superglobal $_SERVER. ``` --- I believe pure functions could bring benefits in certain areas. Today, tools such as PHPStan, Psalm and PhpStorm accept annotations such as @pure, but nobody guarantees that the function respects them. With a native attribute, that guarantee would become the responsibility of the language itself. Moreover, we would have the common benefits of pure functions: - it would be easier to read and test a function, since the result would depend only on the arguments, without needing mocks for global state, session or file system - the result of a pure function could be cached (memoization) without changing the behavior of the program - the compiler and OPcache could, IN THE FUTURE, optimize calls with constant arguments - it would be safer to execute the code in Fibers or in extensions such as parallel, since there would be no shared state However, if you find the idea interesting, the points about the implementation arise. I am not a great connoisseur of php-src, but I believe it would be necessary to: - compile-time validations, to reject the use of $this, superglobals, static properties etc. inside a pure function - checking the calls. When the target is known at compile time, such as random_int, the fatal error could be emitted there. But, for dynamic calls, such as $fn() or $obj->foo() and for functions declared later, the check would have to happen at runtime. - marking internal functions that are pure as pure. I would like to hear the list's opinions on this idea. What do you think? Regards, Pedro Veloso

« previous php.internals (#132643) next »