This is an old revision of the document!
Request for Comments: Enum
The old (Pierrick) version of the enum RFC can be found at https://wiki.php.net/rfc/enum?rev=1302087566
- Version: 1.0
- Date: 2010-05-21
- Author: Pierrick Charron pierrick@php.net
- Status: Under Discussion
- First Published at: http://wiki.php.net/rfc/enum
This RFC is about adding the enum language structure.
Introduction
When writing a program, it is often required to create lists of constants representing integers to make the code more readable. This RFC introduce a new language construct to define such a list by assigning unique arbitrary values or not.
Why do we need enum
Frequently developers need to produce code like this:
const LOG_LEVEL_DEBUG = 1, LOG_LEVEL_INFO = 2, LOG_LEVEL_WARNING = 3, LOG_LEVEL_ERROR = 4; // Or class Tokens { const T_IF = 258, T_ELSE = 259, T_WHILE = 260, T_DO = 261; }
The proposal is that this could be written in a much more concise manner:
enum { LOG_LEVEL_DEBUG, LOG_LEVEL_INFO, LOG_LEVEL_WARNING, LOG_LEVEL_ERROR }; // Or class Tokens { enum { T_IF = 258, T_ELSE, T_WHILE, T_DO }; }
Proposal and Patch
namespace Cards; enum Suit { SPADES => '1', HEARTS => 2, DIAMONDS, // Will have value 3 CLUBS, // Will have value 4 } var_dump( Suit::SPADES ); // enum(Cards\Suit)(1) var_dump( Suit::SPADES == 1 ); // bool(true) var_dump( Suit::SPADES === 1 ); // bool(true) - because the value is cast to an integer upon declaration var_dump( Suit::SPADES == '1' ); // bool(true) var_dump( Suit::SPADES === '1' ); // bool(false)
Declaration
The keyword enum
is reserved. An enum may be defined wherever a class
or interface
could be defined, and the same namespacing, naming and referencing restrictions apply.
Within the enum is a comma-separated list of variable names. Each variable name may optionally be followed by the array operator =>
and a value. The same logic is used for assigning values to the enum members as for assigning keys to arrays: for explicit assignments the same casting of numbers to integers is used, and for implicit assignments the smallest non-negative integer greater than all the previous values is used. Unlike array declarations, however, a duplicate value causes a fatal error.
Use
An enum member may be referenced as EnumName::VALUE
just like a class constant.
A scalar may be (explicitly or implicitly) cast to an enum member:
// Using declaration of Suit above var_dump( (Suit)1 ); // enum(Cards\Suit)(1) var_dump( (Suit)true ); // enum(Cards\Suit)(1) var_dump( (Suit)('one') ); // null
An enum may be cast to another type by applying the normal cast operations to its value.
An enum member satisfies the is_*() tests that would be satisfied by its value, but also a new is_enum()
function is introduced. This apparent inconsistency is equivalent to the situation with callables, where a string satisfied both is_string()
and is_callable()
, so is not without precedent.
// Using declaration of Suit above var_dump( is_string( Suit::SPADES ) ); // bool(false) - since the value is an integer var_dump( is_int( Suit::SPADES ) ); // bool(true) var_dump( is_enum( Suit::SPADES ) ); // bool(true) $spades = Suit::SPADES; var_dump( is_enum( $spades ) ); // bool(true) var_dump( is_int( $spades ) ); // bool(true) // Compare: function callableFunction(){} $callable = 'callableFunction'; var_dump( is_callable( $callable ) ); // bool(true) var_dump( is_string( $callable ) ); // bool(true)
Possible alterations
- Requiring the existing
const
keyword before the enum; this largely eliminates B/C issues.