Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:107992 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 85919 invoked from network); 5 Jan 2020 20:20:06 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 5 Jan 2020 20:20:06 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 12B9D1804D1 for ; Sun, 5 Jan 2020 10:24:47 -0800 (PST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-wm1-f51.google.com (mail-wm1-f51.google.com [209.85.128.51]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Sun, 5 Jan 2020 10:24:46 -0800 (PST) Received: by mail-wm1-f51.google.com with SMTP id b19so12784260wmj.4 for ; Sun, 05 Jan 2020 10:24:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=subject:to:references:from:message-id:date:user-agent:mime-version :in-reply-to:content-transfer-encoding:content-language; bh=CK0bc6SjPMJp1FWh0NmsuqWg+SdbomVyOQmU2FKfHDI=; b=cQDfVYrkDqwa2f3fuw24tP3AH5kTSifHnl62VSz339jSScT0KaqJrya+GuMRg/Po0d qmQa2CUUV+bS2p0ShjKCfMklKilhFfOvKoTOpKx9OPcfO7aE6hyP+dYAB8asb7ab32vW 6c2anNlcdioNakB5TvkE76w+mROmAyV5ef6eyglGI3jRflH+NThSVKIPBSWsH1WlZoEr gNxYpKTTUCDxSLy0zgIzGvGyfgMnOsykqN6qLN95OEyNw1CzOzMv3VjLi5LBoZHl6ljc 0Iqypd2Hj1VGa4s7AV8zFu9YjRpLr7MbPK8PTcYq22fzX6waRq4JxiMBMvVRD8jEgsPL xciw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-transfer-encoding :content-language; bh=CK0bc6SjPMJp1FWh0NmsuqWg+SdbomVyOQmU2FKfHDI=; b=mFWBuoDRQMAZxkixSr2Q+5Douq2a9m1xPs1xiA9Njpzd4+O8JzUvJy1PKi0+dtYPPT v2D19za38vxjXyC/iseHALdOmzE/SeHTJJmhKB8Lh+Nu3J1GvLboMIeUdvlRjO/FchUq +gPPvXjR5SmQ4CPgWNCU/6wjfRJpcwvobyGymFXIAp8I7Iueg/I8oOMvkJ3bxwdd5yUQ jHfdok8UnnwdiQQU5k48h/f/ookbwYxS8LWeiiZggB1F8uhJZ5WlLWcqyV9NOBNHPq9t /XNWKj01ZVXbyzCibjZE20oDWslrWveqx5Qya4dTBkaubN4ecuVs03QfFvgAIMmn+VTc QJYQ== X-Gm-Message-State: APjAAAWdUor/WEHkB4zwZoF6AnCanptesM0WFQx5gsKRG8ZKKyGjHoQx qBAO4taBbUXb8TybAz3KsKhIpxlL X-Google-Smtp-Source: APXvYqw5XS7nKLpCl4gDKlvEdyB7cWCCjc0pQaGSX2UpKV00crKJ9hrJ8rmbtI7BGye2K0cVlNGF+w== X-Received: by 2002:a7b:cc09:: with SMTP id f9mr30988958wmh.71.1578248683245; Sun, 05 Jan 2020 10:24:43 -0800 (PST) Received: from [192.168.0.14] (cpc84253-brig22-2-0-cust114.3-3.cable.virginm.net. [81.108.141.115]) by smtp.googlemail.com with ESMTPSA id 18sm19872822wmf.1.2020.01.05.10.24.42 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 05 Jan 2020 10:24:42 -0800 (PST) To: internals@lists.php.net References: <5e0d723f.1c69fb81.e2ae8.24e2SMTPIN_ADDED_MISSING@mx.google.com> <74F2DBFC-E63C-428C-A37F-2D0CEE15AD0F@newclarity.net> Message-ID: <53556dfb-44ce-f902-204c-9a7da9484a61@gmail.com> Date: Sun, 5 Jan 2020 18:24:39 +0000 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Thunderbird/68.3.1 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-GB Subject: Re: [PHP-DEV] Initializing constants once, with code? From: rowan.collins@gmail.com (Rowan Tommins) On 04/01/2020 22:40, Mike Schinkel wrote: >> Add in the "initialise on first read", and you end up with 4 lines per pseudo-constant vs 5 per method: > But then you give an example which exaggerates in the other direction. No, I gave an example of exactly what it would like if I wrote it: one line methods with one line docblocks, or one line constants with one line docblocks. The only difference in your example below is that you've omitted the docblocks from both versions, saving one line on each. > class Environments { > const PRODUCTION = 'master'; > const STAGING = 'stage'; > const TESTING = 'test'; > const DEVELOPMENT = 'dev'; > } > > vs. > > class Environments { > static function PRODUCTION() { > return 'master'; > } > static function STAGING() { > return 'stage'; > } > static function TESTING() { > return 'test'; > } > static function DEVELOPMENT() { > return 'dev'; > } > } This is a really terrible example, because it's basically an enum, and would never be anything other than a set of true constants. In a sense, that's nitpicking at the example, but I think it's teling: the kinds of constants that are "scannable" are generally not the kind that would be replaced by configuration in the way you're suggesting. That is, if you have: class API {     const TEST_URL = 'https://testing.api.example.com';     const LIVE_URL = 'https://production.api.example.com'; } ...then these are nicely "scannable", but already capture the fact that there are different options to choose from. If instead you have: class API {     const URL = 'https://production.api.example.com';     const VERSION = 1.5; } ...then being "scannable" isn't particularly relevant, because these are completely separate values. > What I am asking for is the ability to _evolve_ code over time and not force code to forever retain its technical debt simply because of initial choices. > > And not just for constants, but for evolvability of all code. To me that seems like such a no-brainer best practice for programming language design that I am struggling to understand the fundamental objections to it. I suppose it would be possible to design a language which maximised "evolvability" by using interchangeable syntax for different concepts. For instance, properties and constants could all just be special method calls; perhaps "const FOO=42" would be sugar for "static function FOO() { return 42; }" and "SomeClass::FOO" would always be the same as "SomeClass::FOO()". However, there will always be new requirements that require a breaking change. For instance, maybe you need to send some API calls to one URL and some to another, so everywhere that fetches the URL needs to choose between two constants, or pass a parameter to the method. Or maybe you write something as static and later wish you'd required an instance to be constructed. So it's not enough to say "everything should be evolvable", we need to ask whether this specific scenario is common enough to design the language around, and what the possible downsides of the feature might be. > The fact constants are limited to literal code is merely a limitation > of the opcode compiler, not a conceptual difference. In both cases > they are initialized before use, and then never changed. If they are > immutable once initialized, then they are conceptually constants. I disagree, I think constants being a literal value is a design decision, not an implementation one. Off the top of my head, I can think of three types of things that you might call "constants": 1. A value that will never change, and you just want to give a name to. For instance, MINUTES_IN_HOUR=60 2. A value set at compile-time, to hard-code a particular condition. For instance, DEBUG=false 3. A value which is set at run-time, but happens not to change during the course of the application, so should not be over-written. PHP's constants are designed primarily to be type 1 - they are literal values, hard-coded in the source. Unlike C, there is no standard pre-processor for PHP, so type 2 is rarer, but it's possible to implement by manipulating the source file before deployment, or even when running the autoloader. Your proposed feature changes constants to instead be type 3, which I think is a fundamentally different concept - much more like a property with extra restrictions. I think it would be very confusing for the syntax which everyone is used to meaning "hard-coded or at most compile-time value" could now actually mean "global value different on every request": const USER_ID {     return $_GET['user_id']; } > Yet another approach would be for me to ask for would be for a shortened function declaration syntax. But again that would also not empower existing constants to evolve: > > class Environments { > function PRODUCTION = 'master'; > function STAGING = 'stage'; > function TESTING = 'test'; > function DEVELOPMENT = 'dev'; > } During the discussion of short closures a suggestion came up that the syntax could be reused for single-expression methods, so you'd write this: class Environments {    public static fn getUrl() => 'https://api.example.com'; } As you say, that still requires callers to know that they're calling a method, not referencing a constant; we evidently disagree on whether that's a good thing. > Both you and Larry have redefined my use-case to an idealogically > convenient use-case. Can we please address the use-case as I am > defining it: existing code that already uses constants and future code > where developers use constants because of lack of skill, awareness of > "best practices", or too-tight timelines? For my part, I tried to look at the bigger picture, because I think major changes to the language should address as many use cases as possible, not introduce special syntax for narrow scenarios. As Larry mentions, the proposal is also limited by "globalness". Since constants are always static, the initialisation code can only access global and static state, so you can't inject a configuration object into your constructor then use it to initialise constants. And since they're write-once, you can't use them for Laravel-style "facades", where the access is static, but can be swapped out at run-time. Perhaps a better angle to look at is something like the C Pre-Processor - manipulating the code at compile-time so that multiple different versions of the code can be created from the same source, but constants are still constant at run-time. I know there are tools out there already to do this, but have never used one. Regards, -- Rowan Tommins (né Collins) [IMSoP]