On 05/01/2020 21:53, Mike Schinkel wrote:
Yet you called my list of URLs enums, and they are not at all arbitrary and
absolutely want to change.
I apologise - I took a guess without context for how those constants
would be used, but apparently they're something rather different.
I take it you have never used Pantheon hosting then? You create a named
environment to match a Git branch.
I'm still struggling to understand why you need multiple constants, all
mutable based on some other dimension. If the ultimate goal is to know
the name and branch of the *current* environment, how do the constants help?
It seems on the face of it like the constants have outlived their
usefulness, and need to be replaced by a lookup table of some kind.
What is "better" in this context is one's opinion. You might not find
it beneficial, but I would.
Agreed. I actually said the same in one draft reply, but maybe deleted
it while editing down.
"Constants are defined at compile-time" is a status quo in the same sense as
"variables can be assigned to" is a status quo - you could certainly design a language
differently, but it's not just something that happened by accident, it's a design decision.
It was a design decision in that maybe it did not occur to them that it would
be useful; IOW a design by omission.
We'll just have to agree to disagree here. I stand by the assertion that
"compile-time constants" are a well-defined feature, whose restrictions
are part of their definition and purpose.
Ruby has the .replace method for constants and can thus assign at runtime:
=========
https://stackoverflow.com/a/6712438/102699
That method is not actually a feature of constants, its abusing the fact
that everything is an object, so the *value* of a constant might still
be a mutable object. It's an interesting "cheat", but it's not really a
deliberate language feature.
C++ has const member functions (not exactly the same, but similar):
=========
https://www.linuxtopia.org/online_books/programming_books/thinking_in_c++/Chapter08_014.html
Unless I'm missing something, this isn't really related to anything
we've been discussing, it just happens to use the keyword "const".
Python adds a final qualifier to turn variables into constants. Thus is
supports initializing constants:
=========
https://stackoverflow.com/a/47821212/102699
http://code.activestate.com/recipes/65207-constants-in-python/
Those links seem to say that Python doesn't have constants *at all*, but
you can emulate them in various ways. As such, you can give them pretty
much whatever behaviour you like, since you're defining the language
feature from scratch.
Javascript can assign constants at runtime:
=========
fn = function() { return "World"; };
const who = fn();
alert( "Hello " + who );
This is a more interesting case; some properties to ponder:
- implemented as a special kind of variable (e.g. they have the same
scope rules and syntax as "let" variables)
- can be global or block-scoped, but not a property of an object
- cannot be pre-declared before they are assigned, or automatically
initialised on first reference
- can contain any value, including mutable objects
Java creates class constants with `public static final` which can be
initialized with code:
=========
https://www.javaworld.com/article/2076481/use-constant-types-for-safer-and-cleaner-code.html
Another interesting case:
- implemented as a special kind of variable
- can contain any value, including mutable objects
- will raise an error if the compiler cannot prove there is exactly one
assignment; i.e. these are not purely run-time constructs like PHP's
define() constants
- can be static members of a class, and include an inline initializer
- can be static members of a class and have no inline initializer, in
which case they *must* be initialized using a "static initializer block"
which will be run the first time *the class* is referenced at run time
(a bit like substituting the value during autoloading in PHP)
- can be instance fields, and must be initialised inline, or in every
possible constructor
- can be block-scoped variables, and must be initialised before first use
The interesting thing here is that the constants are initialised the
same way as any other variable, not using any special on-demand code.
Because of the language's design, the compiler is able to prove that
they are assigned exactly once. That proof is probably a lot harder in
PHP, and the check would probably be punted to run-time.
The biggest sticking point in my mind is your insistence that they share
syntax with constants, rather than variables. This means they can only
be used in static class or namespace context, not against an instance.
It also means *widening* the meaning of a construct, rather than
*narrowing* it: the "final" keyword in Java doesn't let variables do
anything new, it just restricts them; your proposed constant
initialization would allow constants to act in new ways, including
holding complex, mutable types. That's likely to cause confusion for
both humans and tools written based on the current concept that a
constant can always be computed at compile-time.
It's a limitation in the very basic sense that it limits what you can do. You
can't write this, for instance:
class API {
private $config;
public function __construct($config) {
$this->config = $config;
}
const URL {
return $this->config->getValue('API_URL');
}
}
But you could do this:
class Api {
const URL:string {
return Config::get()->api_url;
}
}
The difference is that a Java-style "final variable" can have a single
value *per instance*, so this is valid:
class API {
private final $URL;
public function __construct($config) {
$this->URL = $this->config->getValue('API_URL');
}
}
I'm just looking for solutions to your use case, which as I understand it is
values which change rarely based on configuration.
I honestly do appreciate it. You are generally very good about that kind of
thing.
I would be interested to hear more about why you think pre-processing
doesn't suit your use case. It seems like a good fit to me:
- naturally fits with code expecting compile-time constants
- no run-time overhead if done as part of deployment
- can be implemented using succinct syntax, rather than run-time
initialisation code
Regards,
--
Rowan Tommins (né Collins)
[IMSoP]
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php