> On Jan 5, 2020, at 12:02 PM, Larry Garfield <la...@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

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to