On Tue, 7 Jan 2020 at 01:13, Mike Schinkel <m...@newclarity.net> wrote:

> At least two come to mind:
>
> 1. Guard clauses for code you only want to run in one environment and not
> another.
> 2. Common code that is used by different websites.
>


It seems to me that there are two different concerns there:

- An enumerated set of environments that never changes, which code can
associate logic and configuration with. That maps well to PHP's constants,
and would be even better with an enum type.
- A mapping from that set of environments to a set of branches, which is
initialised at run-time based on environment information. That sounds like
an associative array with the environments as keys.

So at its simplest, I would write something like this:

class Environments {
   const PRODUCTION = 4;
   const STAGING = 3;
   const TESTING = 2;
   const DEVELOPMENT = 1;

   public static $branches = [
        self::PRODUCTION => 'master',
        self:: STAGING = 'stage',
        self:: TESTING = 'test',
        self:: DEVELOPMENT = 'dev',
    ];
}

That way, you can write code like "if ( $currentEnvironment ==
Environments::PRODUCTION )" without caring about the complexity of mapping
branches to environments. You can also associate other data with each
environment - maybe there's a database name for each environment as well,
for instance.





> 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.
>
>
> The .replace is not a deliberate language feature?
>


It's not a feature of constants, it's a feature of strings and arrays,
because they are implemented as objects. The same trick would be possible
in PHP if constants could have objects as values:

const FOO = new DateTime('today');
self::FOO->modify('+1 day');

The constant FOO hasn't changed value, but the object it points at has been
mutated.

In Java, the same would be possible with an Array, but not a String,
because although they're objects, strings are designed as immutable.



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.
>
>
> Yes. IOW, Python did not feel there was a need for a compile-time constant.
>


Or maybe everybody really wishes it had them, but nobody's come up with an
implementation that fits into the language design?




> I can already use static variables, and the immutability is not that
> important to me.
>
> It's the desire to be able to start as statically declared constants and
> evolve later to dynamically initialized.
>



If we take these two statements really literally, you can do everything you
want already: start with a static variable which you don't change (but
isn't guaranteed immutable), then evolve later to initialise that variable
dynamically.

Maybe your use case would be solved by making the syntaxes for accessing
constants and static variables interchangeable, so that Foo::BAR and
Foo::$BAR could reference either? Unfortunately, it's currently possible
for both of those to exist at once, so that's probably not going to work.




> As for immutable variables, I see those as very useful to, but I think
> their use-cases are orthogonal to the use-case I was trying to address.
>


Then all the JS and Java examples aren't going to help your argument,
because those are most definitely immutable variables, not compile-time
constants extended with initialisation syntax.




> 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.
>
>
> But isn't that often the point of new features; to allow for doing things
> in new ways?
>


Sometimes, yes. Sometimes it's to provide safety, or elegance of
expression, without adding any new behaviour at all.

My point was that more assumptions will break if you widen the meaning of
"constant" than if some variables are marked immutable.




> I often chuckle when I hear that something might cause confusion as an
> argument against adding to PHP because it makes me think of PHP generators,
> generator return expressions and Generator delegation!
>
> I assert that if we can add generators (and in the future, generics!) then
> most anything we could add is going to be less confusing. :-)
>



For the record, I think generators are a really neat feature, but
absolutely hate that they are declared with the "function" keyword, and
hate that they reuse the "return" keyword for "set final value".

So, yes, that's a good example of something that breaks people's
expectations of what keywords mean, and I think that's a bad thing.




> and tools written based on the current concept that a constant can always
> be computed at compile-time.
>
>
> My assumption is that the tool would simply be updated to recognize which
> constants would be initialized at runtime.
>



I'm not saying it's impossible to account for it, I'm just saying there may
be a lot of tools out there which would need to be updated. Saying "simply"
doesn't make it so!



> The difference is that a Java-style "final variable" can have a single
> value *per instance*,
>
>
> I cannot think of anything conceptual that would keep us from having
> constants per instance, but I don't see a strong need for is so I did not
> propose it.
>


Well, we'd need a new syntax, for a start, since $foo->bar already accesses
a property.




> I would be interested to hear more about why you think pre-processing
> doesn't suit your use case.
>
>
> When I think of pre-processor, I think of textual substitution.
>


I was thinking much more abstractly: some code of some sort that runs as a
separate build step, and produces some kind of output that can be
referenced cheaply at run-time.

In particular, I was imagining the pre-processor being fully aware of the
language's syntax, and operating at the AST level. You could view it as an
extension of compiler optimisations: explicitly saying "run this before you
even deploy to the server, the result will never change".

The output to PHP is necessary for the same reason client-side languages
are transpiled to JavaScript - it's the language spoken by the target
run-time. If we could treat OpCodes as a stable target, like .NET CLI, or
Java bytecode, it could target that instead, but it wouldn't actually make
much difference to the operation of the pre-processor. There is of course a
side-effect that the resulting PHP code can be read by a human, making it
easier to debug.

Regards,
-- 
Rowan Tommins
[IMSoP]

Reply via email to