> On Jan 5, 2020, at 3:17 PM, Rowan Tommins <rowan.coll...@gmail.com> wrote: > > They seem a poor example of something that you would later want to "evolve" > using the proposed new feature. An enum is, by definition, a set of values > that covers all possibilities, often with completely arbitrary values.
Yet you called my list of URLs enums, and they are not at all arbitrary and absolutely want to change. We can both agree that enums for 0, 1, 2 etc. are not in use-case I am discussing. Maybe you misspoke when you called my list of URLs enums? Or I misread? > I'm struggling to imagine how this would work. I've seen plenty of code that > needs to know "the current environment", but "the name of the current > development environment" seems an odd thing to have a constant for. I take it you have never used Pantheon hosting then? You create a named environment to match a Git branch. "dev" is not "local" in this content. "dev" is the place developers push code to test remotely. Then they push to "test" for QA to evaluate. At least for this client. That said, my client wants to move to many "dev" and "test" environments, one for each JIRA epic, so we would like to be able to initialize the API urls based on the current subdomain. > Well, it would be more "scannable" if every method in the class was written > on one line - and indeed you can do so if you want - but that's not > inherently better. What is "better" in this context is one's opinion. You might not find it beneficial, but I would. > If a class has a bunch of different functions and constants in, I'll > generally use an IDE or editor plugin to navigate them, and rely on them > being well-named, rather than minimising the whitespace between them. I use and have used PhpStorm extensively, since prior to 1.0. But PhpStorm does not make it easier to do code reviews on Github, or even read code in PhpStorm. Yes, I can navigate them, but to still adds cognitive load. Honestly, we are debating preferences here. Can we focus on objective things? > "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. Design decisions can be changed. PHP 5 changed the design decisions of PHP objects and added the __set() method. Before then it could have easily been argued that variable accessed a memory location, but never called code. But then that design decision was changed. So there is no reason I've heard thus far that this one could not be changed too. > An interesting exercise is to ask if there are other languages that take a > different decision - it's not decisive, either way, but it can be suggestive. > "Can constants be evolved into something that is initialised on-demand?" is > not something I'm aware of examples of elsewhere. That could be because > nobody's thought of it before, or just that I haven't come across it, but it > could be because there's a better solution to the underlying requirement. Excellent point. Ruby has the .replace method for constants and can thus assign at runtime: ========= https://stackoverflow.com/a/6712438/102699 Javascript can assign constants at runtime: ========= fn = function() { return "World"; }; const who = fn(); alert( "Hello " + who ); 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 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/ 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 I think that is a fairly conclusive list of highly-used languages, all of which allow constants to be initialized with code. This list would imply any assertion that constants must be handled at compile time is not applicable for many other languages so I would argue to not a universal principle. Also it would imply that allowing constants to be initialized via runtime code would not disrupt the time-space continuum, either. > I think the syntax being the same when you *reference* the value bothers me > more than how it is declared. If I see ClassName::USER_ID, I expect the value > to be the same each time the code runs, and to be able to find the value > directly in the source. Again, I ask if that your unease has more to do with status quo bias vs. something fundamentally wrong with the concept? > 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; } } class Config { public $api_url; private static $_current; function __construct($args = array()){ $this->api_url = $args['api_url']; } static function get():Config{ if ( ! isset( self::$_current ) ) { trigger_error('must call Config::set() before calling Config::get()'); die(); } return self::$_current; } static function set( Config $config ){ self::$_current = $config; } } Config::set( new Config(['api_url' => 'https://api.example.com']) ); //... $api_url = Api::URL; Any way, why again must perfect be the enemy of the good? > Laravel's "facades" are global variables hidden behind static methods. So you > write "DB::query($sql)" as a short-hand for > "DB::$currentInstance->query($sql)". Most of the time, you just treat it as > static, but if you want to write tests, for instance, you can inject a mock > as the current instance. Ah. > An interesting thing is that you can evolve a class that really is static and > replace it with one of these facades. Unfortunately, the same wouldn't be > true with initialise-once constants, because once the constant had been read, > you couldn't swap it out in another test. Well, I am suggested one-time only because I assumed that one-time only _is_ the only thing that is fundamental to `const.` But I can see uses for being able to redefine them — when running unit tests — but I was not planning to ask for that. > Many people would say the kind of global state you're talking about is an > anti-pattern. Well, Larry did, which is reality is an appeal-to-authority argument and not an argument on the merits. But I used "anti-pattern" because I did not think I was trying to convince anyone against adding a pre-processor, so it was just easier to write! > 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. -Mike -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php