Re: Initializing constants once, with code?
| From: | Mike Schinkel | Date: | Tue, 07 Jan 2020 00:29:56 +0000 |
| Subject: | Re: Initializing constants once, with code? | ||
| References: | 1 2 3 4 5 6 7 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-108018@lists.php.net to get a copy of this message | ||
> On Jan 6, 2020, at 4:24 PM, Larry Garfield <larry@garfieldtech.com> wrote:
> For example:
>
> const DEBUG_MODE = false;
>
> function foo() {
> if (DEBUG_MODE) {
> // Do stuff.
> }
> }
>
> PHP will currently (AIUI) inline the DEBUG_MODE value at compile time, notice that the code
> path is unreachable, and omit it from the compiled opcodes entirely. (I'm pretty sure it does
> that now, at least; if not, it certainly can be.)
>
> If you use a define, however:
>
> define(DEBUG_MODE, $_ENV['debug'] ?? false);
>
> function foo() {
> if (DEBUG_MODE) {
> // Do stuff.
> }
> }
>
> That optimization cannot happen. But just from looking at foo() I cannot tell which is going
> to happen. I view that as a negative.
To be fair, you cannot tell in the first case either, unless your constant is in the same context as
foo(), which it typically would not be.
You can track down DEBUG_MODE and know it is fixed, but if you ship the code for someone else to set
DEBUG_CODE, you can't know what they will set too. So I am not seeing a big distinction other
than with compiler optimization. And if the alternative is to use a function, that can't be
optimized any better so it seems moot to me.
> No, it's because you cannot override them. It makes the conditional logic around defining
> them more complicated. Specifically, with WordPress for example,...
Ah! You and I actually are on the same page there.
I have a project that is a local development environment (WPLib Box) and wp-config.php's
structure has been a huge PITA for us. I am completely in sync with you here.
In fact I wrote an alternate wp-config to resolve that problem, but then had to task switch and I
have not put any effort into evangelizing it:
- https://github.com/wplib/better-wp-config
Which brings up the point; it would be *really* great if we could redeclare declare() constants in
PHP, for automated testing purposes.
> Now suppose you have a lazy-loading "constant" that uses $_GET. If it gets called
> before that conversion happens in some code paths but not others, its value will be unpredicatable.
> It may get built before $_GET['q'] is changed or after, which would change its value.
I concur. However, if I do that in a function it will be the same issue.
I think it just comes down to us having a different value judgement. To me I don't see it being
a problem if the bug is in a constant or a function — it is still a bug — but you clearly
classify those differently.
> That's not something I ever expect a "constant" to do.
To be fair, if constants were able to be dynamically initialized in PHP 8.0, you could change your
expectation.
But as you say, that's not your preference.
> (Is this a subjective and partially emotional interpretation? Of course it is. Much of
> language design, like any other design, is. But I don't think my subjective view here is
> unique.)
Maybe for PHP. But clearly the designers of Ruby, Javascript and Python thought differently, no?
> The specific use case you presented is not one I believe PHP should support. If I have not
> convinced you of my position on that yet, I don't think I am going to, nor are you going to
> convince me of yours.
Fair enough. So if I were to create an RFP you'd get a vote "no", and sadly I will
not get a vote. So it depends what others think.
> Certainly. But a good language nudges people toward writing good code, or at least not-bad
> code. (How hard it should nudge is a subject of much debate and is one of the reasons we have many
> languages.)
I strongly agree with that.
I just disagree with your assertion that what I am proposing would result in "bad" code.
> That wasn't what I was thinking of, although I suppose that's also a concern. I was
> more thinking of the inconsistent initialization time, as in my earlier example, leading to a
> constant that is variable request-to-request even if it's nominally constant-once-set within a
> specific request. That's a very different behavioral pattern from guaranteed consistent
> request-to-request. IMO they should remain separate.
Okay. Thank you for engaging. I think we have ended up having a well reasoned discussion and have
laid out our respective positions succinctly. You feel strongly that inconsistent initialization
would be a concept and I few that as just bad coding that would need to be fixed no matter if the
code initialized a constant or if it ran through a function.
I guess we'll just have to see how others feel about the subject.
-Mike
P.S. another use-case I remembered for constants is poor-man's class annotations, which I
actually use a lot. For example, I use a POST_TYPE constant in a class designed to load a WordPress
post of the given type. It would be really nice to be able to initialize those types of constants
differently based on testing vs. production.