Straw poll: Places to allow function calls in constant expressions

php.internals

tyson andre

6 years ago
Hi internals, I've created a straw poll at https://wiki.php.net/rfc/calls_in_constant_expressions_poll , to measure interest in allowing calls in different types of constant expressions. If there aren't any problems with the poll structure or rules preventing creating a poll, I was going to add it to the rfc index page and move it to voting. This poll was created to gather opinions on which of the below statement types would be desirable to change, and in which ways, before rewriting https://wiki.php.net/rfc/calls_in_constant_expressions . It seems desirable to change some of these expression types (e.g. parameter defaults, static properties, static variable defaults) in different ways from others. (e.g. forbidding static property declaration expression results from containing objects seems like a completely unnecessary limitation from trying to reuse the implementation, in retrospect). This poll was created for feedback on whether changes to the following places had support, and what types of changes there were interest in. - Initial values of static or instance properties. This poll only addresses static properties. - Parameter defaults of functions, methods, and closures. - Class constant values. - Global constant values. - Static variable default values. I'd asked earlier about creating a poll in https://externals.io/message/108430 , but didn't receive a response. Thanks, - Tyson

Mark Randall

6 years ago
On 17/02/2020 02:08, tyson andre wrote:
> I've created a straw poll at https://wiki.php.net/rfc/calls_in_constant_expressions_poll , to measure interest in allowing calls in different types of constant expressions.
I've yet to make my mind up for most circumstances, although I'm leaning towards a general "No". What I can't express on this strawpoll though, is that I would unequivocally vote against "any function or method call" in all circumstances.
-- Mark Randall marandall@php.net

tyson andre

6 years ago
Hi internals, > I've created a straw poll at https://wiki.php.net/rfc/calls_in_constant_expressions_poll , to measure interest in allowing calls in different types of constant expressions. > If there aren't any problems with the poll structure or rules preventing creating a poll, I was going to add it to the rfc index page and move it to voting. This straw poll has been moved to voting and added to the rfc index page. The poll will be closed on March 4th. Thanks, - Tyson

Bishop Bettini

6 years ago
On Wed, Feb 19, 2020 at 12:58 PM tyson andre <tysonandre775@hotmail.com> wrote:
> Hi internals, > > > I've created a straw poll at > https://wiki.php.net/rfc/calls_in_constant_expressions_poll , to measure > interest in allowing calls in different types of constant expressions. > > If there aren't any problems with the poll structure or rules preventing > creating a poll, I was going to add it to the rfc index page and move it to > voting. > > This straw poll has been moved to voting and added to the rfc index page. > The poll will be closed on March 4th. >
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. 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. 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 ?> Trying to do the same for global constants, static variables, or function default parameters resists a similar initialization mechanism because we don't have defined common entry point analogues. If we had a main(), or if we had framed @before decorators, we could do something similar, but we don't -- so I feel we should leave these off the table. Thank you, Tyson, for taking the time to progress this feature. [1]: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/static-constructors

Mike Schinkel

6 years ago
> On Feb 19, 2020, at 2:00 PM, Bishop Bettini <bishop@php.net> wrote: > > 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 > ?> > > Trying to do the same for global constants, static variables, or function > default parameters resists a similar initialization mechanism because we > don't have defined common entry point analogues. If we had a main(), or if > we had framed @before decorators, we could do something similar, but we > don't -- so I feel we should leave these off the table.
For different reasons than this RFC I have wanted a static class constructor for a really long time. I hope this is something we can seriously consider. Thanks Bishop for proposing it. -Mike

tyson andre

6 years ago

Nikita Popov

6 years ago
On Mon, Feb 17, 2020 at 3:09 AM tyson andre <tysonandre775@hotmail.com> wrote:
> Hi internals, > > I've created a straw poll at > https://wiki.php.net/rfc/calls_in_constant_expressions_poll , to measure > interest in allowing calls in different types of constant expressions. > If there aren't any problems with the poll structure or rules preventing > creating a poll, I was going to add it to the rfc index page and move it to > voting. > > This poll was created to gather opinions on which of the below statement > types would be desirable to change, and in which ways, before rewriting > https://wiki.php.net/rfc/calls_in_constant_expressions . > It seems desirable to change some of these expression types (e.g. > parameter defaults, static properties, static variable defaults) in > different ways from others. > (e.g. forbidding static property declaration expression results from > containing objects seems like a completely unnecessary limitation from > trying to reuse the implementation, in retrospect). > This poll was created for feedback on whether changes to the following > places had support, and what types of changes there were interest in. > > - Initial values of static or instance properties. This poll only > addresses static properties. > - Parameter defaults of functions, methods, and closures. > - Class constant values. > - Global constant values. > - Static variable default values. > > I'd asked earlier about creating a poll in > https://externals.io/message/108430 , but didn't receive a response. > > Thanks, > - Tyson >
Hey Tyson, I feel like the results of this poll aren't going to be particularly meaningful, because it gets too caught up in the details and loses track of the big picture. If you ask people whether they want to allow function test($param = some_call()) { } they're going to to tell you "no", because that seems pretty esoteric and most people likely do not see a use-case for it. If you ask the same people whether they want to write function test(Dep $optionalDep = new Dep()) { } instead of function test(Dep $optionalDep = null) { if ($optionalDep === null) { $optionalDep = new Dep(); } } a lot of them are probably going to tell you "yes" now. The question didn't really change (new Dep is just a different type of "function call"), but the perception changes a lot. This is also why I think the focus on plain function calls in particular is somewhat detrimental. This is one of the cases where going for a paradigm shift (constant expression -> any expression) is "simpler" than doing an incremental change (extending constant expressions to allow function calls, and all the subtleties that entails.) Regards, Nikita

tyson andre

6 years ago