Re: Initializing constants once, with code?
| From: | Mike Schinkel | Date: | Sun, 05 Jan 2020 18:34:58 +0000 |
| Subject: | Re: Initializing constants once, with code? | ||
| References: | 1 2 3 4 5 6 7 8 9 10 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-107993@lists.php.net to get a copy of this message | ||
> On Jan 5, 2020, at 12:02 PM, Larry Garfield <larry@garfieldtech.com> wrote:
>
> I am saying that the behavior of a constant is that it is... constant. A proper constant is
> evaluated at compile time and appears as a literal in the final runtime code, with no dereferencing.
> AIUI,
const in PHP does exactly that, in contrast to
> define. That is fundamentally conceptually incompatible with a
> value that is derived at runtime and happens to use constant-style syntax.
Here is the problem with the crux of your argument. You are stating as a postulate that which you
have not proven. The only reason constants are defined at compile time is that they have always been
defined at compile time.
There is _no_ reason — unless you can elaborate a specific tangible reason — why a constant
_must_ be defined at compile time vs. first access. Doing the later does not change its essential
state, i.e. it will still be "constant" and not change.
You are arguing from the perspective of a status-quo basis that constants are compile because they
thus far have been compile-time. But preexisting implementation is not a valid argument for why
something must continue to be the way it is. Give me a conceptually valid reason why constants can
only be defined a compile time and I may come to agree with you. Otherwise I assert your arguments
are just biased on current implementation.
> 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.
Let's consider the fact that is PHP had never had the define() and instead implemented the
const keyword from the start, and only allowed compile time values. If PHP had done
that, you would be arguing from a status quo bias the same thing about making that dynamic. And it
currently is dynamic which IMO invalidates your argument that constants must be defined at compile
time.
> I am firmly opposed in principle to having a language construct that looks like a constant and
> makes you think it's a constant but is actually a method call that does who knows what.
Can explore why you are opposed to is, and see if we can find a way to address the use-case I
proposed in another way?
> 1) I want an approximately global value that is auto-memoized on first usage, so I can access
> it from anywhere without having to recompute it or do the work of memoizing it myself.
I would rewrite this to say "I want a convenient syntax for values that tend to get hardcoded
by developers that is easy to use and easy to read that is initialized on first usage so that it
behaves like a constant."
> (I wouldn't want to limit it to global-ish things, either, because global-ish things are,
> as stated, bad in every way and should be avoided whenever possible. Yes, I know there's a lot
> of bad code out there already with it; that doesn't mean encouraging it.)
I am going to argue that glob-ish things are _not necessarily_ bad in every way. They are bad when
they introduce coupling and when they are mutable.
Global-ish is much less bad when immutable, and when structured to make tracking down usage easy.
But before you or anyone attacks me for saying this, realize that PHP is filled with globals that
you happily use every day. Class names are globals. Namespaces are globals. Functions are globals.
And AFAICT immutable class constants are no worse globals than class names.
You can easily find where class constants are defined, and with a PHP analysis tool you can easily
find every place where they are used, except for when people are using reflection or dynamic
dispatch but they can do the same with classes and namespaces, so that's not an argument
against class constants.
> For point 2... if you want to change your API, then your API is going to change. That's
> what it means to change an API.
No, I said that I wanted the API to _not_ change. You are the one forcing the change constraint
here. I am arguing code should be evolvable so that APIs do not need to change.
The more a language forces an API to change when requirements change, the more brittle and less
fit-for-purpose the language is. The more a language does not allow refactoring without breaking an
API the more it is a bad language, and that is much worse than some global constants IMO.
> Making code easier to refactor is all well and good, but not if it violates all expectations
> around what a constant is.
Let's explore the second part of this.
Languages change. And some times that changes expectations. To set the constraint that expectations
cannot change is to force a language to be unable to improve.
Some examples of expectation change:
- PHP 7.4 preloading - My expectation is that the class files will be loaded on every page load, but
with preloading they are not.
- PHP 7.4 custom object serialization - My expectation is that the class instance will serialize as
the class was defined, but this changes that.
- PHP 7.3 const case-insensitive deprecation - My expectation that is constants are case
insensitive, but now my expectation is no longer valid.
- PHP 7.3 const string search functions with integer needle - My expectation that is I can pass an
integer, but now my expectation is no longer valid.
I could go on, but I think the point is the change in expectation is not an unreasonable thing to
occur when a language evolves. We all have to continue learning.
> That's probably the better avenue to pursue for option 2, though again it's not one
> that I find worth compromising the language design for.
It many be changing PHP in a way you object to. But it does not "compromise the language
design." That phrasing is a bit inflammatory.
-Mike