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

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to