Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:88312 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 6802 invoked from network); 18 Sep 2015 02:59:04 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 18 Sep 2015 02:59:04 -0000 X-Host-Fingerprint: 68.118.157.39 68-118-157-39.dhcp.mdsn.wi.charter.com Received: from [68.118.157.39] ([68.118.157.39:14493] helo=localhost.localdomain) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id BF/14-19961-4FD7BF55 for ; Thu, 17 Sep 2015 22:59:00 -0400 Message-ID: To: internals@lists.php.net References: <55FB4791.4040807@gmail.com> Date: Thu, 17 Sep 2015 21:58:57 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.2.0 MIME-Version: 1.0 In-Reply-To: <55FB4791.4040807@gmail.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-Posted-By: 68.118.157.39 Subject: Re: Let's discuss enums! From: me@stephencoakley.com (Stephen Coakley) On 09/17/2015 06:06 PM, Rowan Collins wrote: > Hi All, > > This has come up in passing a few times recently, but I'm not sure > there's ever been a dedicated discussion of it: would it be useful for > PHP to have a built-in Enumeration type, and if so, how should it look? > > Many other languages have enum types, with varying functionality. The > central concept is always that there's some declared type with a bunch > of named constants, but beyond that there's a lot of variability: for > starters, is it a type of object, a special way of naming integers, or > an uncomparable type more like booleans and nulls? > > > Here are my thoughts on what I'd like from a PHP enum - I'm not using > "should" in a particularly strong sense, it's just a way of framing the > points of discussion: > > 1) enums should act like values, not mutable objects; an array-style > copy-on-write behaviour would be possible, but it feels wrong to me to > store any state in an enum variable, so just plain immutable would be my > preference > > 2) the members of an enum should have a name which is accesible as a > string, e.g. Weekdays::SUNDAY->getName() == 'SUNDAY' > > 3) there should be no accessible "value" for a member; the value of > Weekdays::SUNDAY is simply Weekdays::SUNDAY, not 0 or 7 or 'SUNDAY' (I'm > thinking that internally, each member would be represented as an object > pointer, so there's no real benefit to forcing people to number > everything like some languages do) > > 4) each enum member should be considered a singleton, in the sense that > you can't construct or destroy one, only reference them; all possible > instances would be created as soon as the enum was defined > > 5) following from (3) and (4), an enum value should compare equal only > to itself, unlike in C# for instance, where it would be comparable to an > integer based on its numeric value; similarly it shouldn't be possible > to cast to or from an enum > > 6) an enum should be able to have additional fields; these would be > initialised in the enum's definition; this is inspired by Java and > Python's ability to pass parameters to the "constructor" of the enum, > but it feels weird to me for any logic to happen in that constructor > other than simple assignments, so I'm thinking of a simpler syntax and > implementation. It also simplifies immutability if no userland code ever > writes to the properties. There may be an important use case for > constructor logic I'm missing though? > > 7) an enum should have default static methods for accessing all the > members of the enum as an associative array > > 8) enums should be a first-class type, is_object(Weekdays::SUNDAY) > should return false, for instance; maybe Weekdays::SUNDAY instanceof > Weekdays should return true though > > 9) additional static and instance methods should be definable, bearing > in mind the immutability constraints already discussed > > > Given the above, I think we might end up with something like this: > > enum Weekdays { > member MONDAY; // if there are no fields to initalise, the member > just needs its name declaring > member TUESDAY ( 2, 'Chewsdae' ); // positional arguments for > populating fields in the order they are defined; a bit like Java, but > without the constructor > member WEDNESDAY { $dayNumber = 3, $sillyName = 'Wed Nose Day' }; > // or maybe a named-parameter syntax to make things clearer > member THURSDAY, FRIDAY, SATURDAY, SUNDAY; // don't force people to > write each entry on its own line; maybe even the "member" keyword is too > much? Member is even a little too much IMO. A comma-separated list syntax would be better, simply because its shorter and more similar to enum syntax on other languages. > public $dayNumber, $sillyName; // fields initialised for each member > > public static function getWeekend() { > return [ self::SATURDAY, self::SUNDAY ]; > } > > public function getZeroIndexedDayNumber() { > return $this->dayNumber - 1; > } > } > > $today = Weekdays::THURSDAY; > foreach ( Weekdays::getMembers() as $day_name => $day ) { > echo $day->dayNumber; > if ( $day == $today ) { > echo "Today!"; > } else { > echo $day_name; // equivalently: echo $day->getName(); > } > } > > // Do we need a static method to access a member by name, or is this > good enough? > $favourite_day = Weekdays::getMembers()[ $_GET['fav_day'] ]; Not sure if this could be allowed, but simply using name interpolation would be better. e.g.: > $favourite_day = Weekdays::$_GET['fav_day']; Similar to $object->$name and nothing to do with StaticClass::$property syntax. > So, what are anyone's thoughts? Am I rambling on too much as usual? ;) > > Regards, > Is there any interest in enum subtypes? As in, allowing each member to also be a class? This would allow algebraic data typing, which would be a pretty powerful addition to the language. -- Stephen