Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:112470 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 7893 invoked from network); 8 Dec 2020 18:45:23 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 8 Dec 2020 18:45:23 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 8ABC11804DD for ; Tue, 8 Dec 2020 10:14:38 -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=0.1 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_LOW,RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,SPF_NONE autolearn=no autolearn_force=no version=3.4.2 X-Spam-Virus: No X-Envelope-From: Received: from wout5-smtp.messagingengine.com (wout5-smtp.messagingengine.com [64.147.123.21]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Tue, 8 Dec 2020 10:14:37 -0800 (PST) Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.west.internal (Postfix) with ESMTP id F2E42D51 for ; Tue, 8 Dec 2020 13:14:36 -0500 (EST) Received: from imap26 ([10.202.2.76]) by compute4.internal (MEProxy); Tue, 08 Dec 2020 13:14:37 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=N20qqE wi3hgCY+gEpxAenoIUzm9Gv1jSZYDiaDZiDAk=; b=XEtIAtG7QCr9DaJHpkJFNJ 0bzMdtf1YjewYJ8Tzk1DLh5Wlc7H2f2X2k12Mbk6qxTHSw7BYDiqKIKiB4jLKY30 MvQd1/Yfv5K37V67SOAkCvKq3j6+GnAAzpE3WRplGO09Htqps7KpAkTuDuSd3PWb Qlj5AqxQttFRS0cED5895yQEtL/OXl2cpzFIYamQbc7glzCAqfXzYbTeFUHpnwBf GCVp6C5RtH7DYDypxNEPvpTErB9Fme+FsKXB0CMgbygZxccYYrS9Tp1RDSjC+3yA jvBaczXm1oR4kpOs7IvkOzIPSCYLHKMYmE80v+TQLQmiwWaXdGTADnRrbc81tC8Q == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrudejiedgudduudcutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd enucfjughrpefofgggkfgjfhffhffvufgtsehttdertderredtnecuhfhrohhmpedfnfgr rhhrhicuifgrrhhfihgvlhgufdcuoehlrghrrhihsehgrghrfhhivghlughtvggthhdrtg homheqnecuggftrfgrthhtvghrnhepgeelgfekudeivddvteffueejffdthfejieevhefg ffekudevkedtvdelvddvffefnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpe hmrghilhhfrhhomheplhgrrhhrhiesghgrrhhfihgvlhguthgvtghhrdgtohhm X-ME-Proxy: Received: by mailuser.nyi.internal (Postfix, from userid 501) id F423414200A2; Tue, 8 Dec 2020 13:14:35 -0500 (EST) X-Mailer: MessagingEngine.com Webmail Interface User-Agent: Cyrus-JMAP/3.3.0-622-g4a97c0b-fm-20201115.001-g4a97c0b3 Mime-Version: 1.0 Message-ID: <5e92a320-49fc-41b0-8969-338d62c98419@www.fastmail.com> In-Reply-To: References: <32277b43-079d-4cd7-a159-8ad555096742@garfieldtech.com> <31c9d66b-771a-35ed-1b11-c681bbcc02c3@gmail.com> Date: Tue, 08 Dec 2020 12:14:15 -0600 To: "php internals" Content-Type: text/plain Subject: Re: [PHP-DEV] [RFC] Enumerations From: larry@garfieldtech.com ("Larry Garfield") On Sun, Dec 6, 2020, at 7:00 PM, Paul Crovella wrote: Hi Paul. Although we're on hold for a bit while Ilija makes some changes in direction (see previous email), I wanted to respond to your concerns in particular because it sounds like you're misunderstanding the scope and roadmap of what we're trying to do. Enumerations, as a general concept, are stateless. Or rather, the idea of state doesn't even apply to them. The integer 5 doesn't have any state of its own. All instances of the integer 5 are logically identical to all other instances of the integer 5. Enumerations are a way to allow users to define that kind of "list of allowed values" where each value is always identical to itself. Depending on the language they often have the ability to define additional operations on that custom type, which are (from what I've found) nearly always implemented in a method-like syntax for simplicity. In most languages that do so it's straightforward because enums are built on top of objects for convenience, but for instance C# doesn't use objects for enums but still has a way to attach method-like functions to them. (See the survey review I did that's linked from the RFC.) That the PHP RFC for enums uses objects internally is incidental. A few people suggested that we use an entirely new zval type for it, which could no doubt be done and achieve the same end syntax but would be a lot more work internally to do. So if you're defining, say, an enum for cardinal directions (North, South, East, West), There are literally only 4 possible values for that type, and those values must always be equal to themselves. Attaching "5 miles" to "South" in one script and "2 km" to "South" in another script is nonsensical, just like attaching "feet" to the number 5 and later changing it to "fingers" just doesn't make any sense at all. That's why, although we are building enums on top of objects, they cannot and must not have mutable state. They can have predefined methods on them that return a static value (such as a label() method), but that doesn't violate the "5 always === 5" rule. So anything that offers a way to violate South === South cannot be allowed. If you want that, then you don't want enums; you want classes. Don't get distracted by the word "singleton" here. That's an implementation detail, not something the user is ever exposed to. It is true that, if you're attaching operations to enum cases that have no state, a method, a static method, and a constant are often interchangeable. A constant is strictly less capable since it cannot have logic, but a method and static method are functionally equivalent. The reason for forbidding static methods and constants is largely simplicity. Instance methods can cover all of those use cases, so it's only one mechanism to code and only mechanism for users to have to think about. "Should I use mechanism X or Y when they are virtually identical?" is a question that is best avoided. Too, it's a lot easier to add features later if we find they would be useful than to take them away if we find they're problematic. For example, the change I just discussed in my previous email about switching to a single class with instances as constants means that static methods can only be on the enum (Suit), because there is no per-case-class to put them on (Diamonds). The same is true of per-instance constants. If we'd promised that those things worked, we wouldn't be able to make this change. If when the dust settles there's a good reason to expand the functionality further in ways that still don't violate "South === South," (such as adding constants to the enum type itself, perhaps) those can be considered at that time. As both Rowan and I mentioned, the long-term plan includes future RFCs for other functionality such as tagged unions. If you want state, then what you want is not an enum but a tagged union. For whatever reason, most languages with tagged unions seem to build them into and onto enums. I'm not entirely sure why, and I'm honestly not 100% convinced that's the right approach in PHP, but that's a debate for a future RFC. Within the scope of this RFC, enums must always obey "South === South", and thus must be stateless. When we get to tagged unions we can and likely will debate how state works there. > Longer term plans are irrelevant except to avoid inadvertently > shutting the door on something. This RFC is up for discussion, and > will be up for voting, in isolation. It has to be able to stand on its > own. This is true up to a point. Yes, each RFC should be able to stand on its own, but that doesn't mean it must be everything and the kitchen sink. Trying to add enums, tagged unions, pattern matching, overridable identity, and generics all at once (since all of those *are* related to each other) would result in a massive and unreviewable patch, a massive and unreviewable RFC, and people not able to follow all the moving parts well enough to comment on them intelligently. That would almost certainly fail. Explicitly setting up a series of RFCs like we're doing is, as far as I am aware, novel for PHP. It's the correct way to handle a larger task like this, however, especially when there clear division points that "chunk" the work in natural ways. Even if enums in this RFC are the only thing that passes, that's still a major win for PHP. It's not as big a win as tagged unions with robust pattern matching and generics on the side would be, but it's still a big step forward. By breaking it into chunks, we make it more likely that as much as can be done will get done, and approved, and into the language, even if the end result is the same feature set when 8.1.0 gets tagged. --Larry Garfield