I have a work in progress wrapper for allowing const-like syntax for global 
constants `static const X = $dynamicExpression;`.
This can be seen in https://github.com/TysonAndre/php-src/pull/10
This is basically a wrapper around if (!defined(...)) { define(...); }
If anyone's planning to implement changes to the way constants can be declared,
then the POC might be worth looking at (e.g. to see what parts of the code 
would need to be changed),
even if their design and approach is different.

- The issues this solves has overlap and differences with what Mike Schinkel 
requests here.
  It's intended as a solution to limitations in different use cases that I've 
encountered/thought about (which this thread reminded me of).

  Notably, this deliberately can't refer to other *dynamic* "static const" 
values that haven't been declared.
- This deliberately limits it to the top-level statements in files
- Class constants below the global 'static const' can then use the eagerly 
evaluated const.

Reasons for me to implement the proof of concept this way:
- defined()/define() is already supported by the engine.
  This is a slight improvement due to shorter syntax,
  and being more certain the const is only set or used in one file.
- Eagerly initialized dynamic constants are easier to reason about in some ways 
(e.g. fetching the constant of an already fetched class is less likely to cause 
pauses or exceptions.)
  This makes un-noticed errors in rare code paths less likely.
- Attempting to support function calls, property accesses, class constant 
accesses (e.g. inherited), and variables in class constants recursively and/or 
lazily
  would probably break a lot of code/assumptions in the php engine.

  I might be mistaken about that, though - I'd be glad if it turned out to be 
easy to implement.

Declaring 'static const' as a top level statement of a function/closure/method 
might also be possible, but would require more work.

------

It's also worth mentioning that some expressions that definitely have constant 
values
can't be written (in a convenient way) because they use syntax that is 
prevented right now, such as function calls, closures, etc.

My preference would be to make it easier to use dynamic expressions, and 
recommend in coding guidelines that
certain types of expressions "SHOULD NOT" be used for constants that vary on a 
particular host.
(network calls, time, etc)

```
const DEFAULT_PAYLOAD = json_encode(['key' => 'value']);
const ALLOWED_ELEMENT_TYPES = array_merge(self::FIRST_TYPES, 
self::SECOND_TYPES);
const ELEMENT_LENGTHS = array_map('strlen', self::ELEMENTS);
```



> For derive-once global constants, you may be looking for define.
> That's a runtime operation and effectively boils down to a set-once global.
> It doesn't help with constants defined in a class,
> but for an already-global constant define already gives you a one-time set 
> operation,
> just not on-demand.

This POC adds an alternate syntax for a set-once global.
It prevents accidentally reusing the same global name in multiple files (e.g. 
with copy and paste),
and lets people looking at it know the constant is only used in that file.

> Another use-case that just occurred to me is to support testing:
> 
> class Api {
>   const URL: string{
>     return $_ENV['EXAMPLE_API_URL'] ?? 'https://api.example.com';
>   }
> }

That example would be written with the POC as:

static const API_URL = $_ENV['EXAMPLE_API_URL'] ?? 'https://api.example.com';

class Api {
  const URL = API_URL;
}
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to