Re: Re: Straw poll: Places to allow function calls in constant expressions
| From: | tyson andre | Date: | Sun, 23 Feb 2020 02:01:49 +0000 |
| Subject: | Re: Re: Straw poll: Places to allow function calls in constant expressions | ||
| References: | 1 2 3 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-108723@lists.php.net to get a copy of this message | ||
> The original motivation was, IIRC, to initialize class constants with an expression.
> Following KISS, I feel we should constrain our efforts to that scope, and that's how I
> voted:
> "Yes" on class constants and static members, "No" on everything else.
I'd also personally found the
static $x = null; if ($x === null) { $x = some_fn();
} pattern inconvenient and wanted that to be just static $x = some_fn(); to make
the initial value some_fn() if possible. It also seemed more readable (e.g.
doesn't matter if some_fn() can be constant).
My personal use case for parameter defaults and global constants isn't as strong (especially
with define()),
but it's still something I'd want.
- I'd be able to use private const FOO_DEFAULT = array_keys(...); function foo($x =
FOO_DEFAULT) {} if constants did pass, so that's less off a concern, and
ensures&makes clear that the expression is only evaluated once, so it might be a better place to
start with.
> As for implementation, we must manage the complexity.
> I'm a hard "No" on restricting use to an arbitrary, variable list of blessed
> functions.
> It's a dev UX nightmare to include a bevy of array_* functions but no str* functions.
If the RFC succeeded with a whitelist, I'd planned to create RFCs to add to the whitelist.
Locale dependency of string functions was the reason for leaving it out initially, since that may
also be a hard "no" for others.
> Consequently, the only way to safely initialize class constants and static members is at
> run-time, and I can only think of one way to do it.
> Apologies if this has already been suggested: taking a cue from C#, a static class constructor
> ([1])
> would allow us to have expression-initialized constants and static members.
> <?php
> class Config {
> public const URL = null; // compile time initialization
> protected static $mtime = null; // compile time initialization
> private static function __constructStatic() {
> $env = json_decode(file_get_contents('config.json'));
> self::URL = $env->url;
> self::$mtime = filemtime('config.json');
> }
> public function reload() {
> if (self::$mtime < filemtime('config.json'))
> self::__constructStatic();
> }
> }
> }
>
> echo Config::URL; // assert: runtime has already called _constructStatic
> $config = new Config; // assert: __constructStatic called only once by runtime
> $config->reload(); // instance may call its own static constructor
?>
This seems to allow the same functionality my RFC would allow, in a slightly different way.
I didn't go with that syntax because it'd move the values of the constants/properties away
from the declaration.
Also, if json_decode() threw, then there would never be a way for a PHP implementation
to initialize self::$mtime in that example, even though they're unrelated in how
they're initialized there.
Allowing calling __constructStatic multiple times (thus assigning to the **const**
self::URL multiple times) would be a significant change to php internals, and out of
the scope of this RFC
https://wiki.php.net/rfc/calls_in_constant_expressions_poll
("Put the RFC(Poll) URL into all your replies.")
- Tyson