rfc:enum_v2
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
rfc:enum_v2 [2020/05/14 14:45] – ++ maxsem | rfc:enum_v2 [2021/02/18 13:14] (current) – Move status to obsolete ilutov | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== PHP RFC: Enumeration type, version 2 ====== | + | ====== PHP RFC: Enumeration type (alternative proposal) |
* Version: 0.9 | * Version: 0.9 | ||
* Date: 2020-05-14 | * Date: 2020-05-14 | ||
* Author: Max Semenik, maxsem.wiki@gmail.com | * Author: Max Semenik, maxsem.wiki@gmail.com | ||
- | * Status: | + | * Status: |
* First Published at: http:// | * First Published at: http:// | ||
+ | |||
+ | //Note: this is a counterproposal to [[rfc: | ||
===== Introduction ===== | ===== Introduction ===== | ||
- | The elevator pitch for the RFC. The first paragraph of this section | + | Traditionally, |
+ | |||
+ | Consider the following perfectly valid code: | ||
+ | <code php> | ||
+ | preg_split($foo, | ||
+ | </ | ||
+ | |||
+ | What will this call produce? I have no idea, either:) | ||
+ | |||
+ | It would be so much better | ||
+ | <code php> | ||
+ | preg_split($foo, | ||
+ | </ | ||
===== Proposal ===== | ===== Proposal ===== | ||
+ | |||
+ | ==== Basics ==== | ||
A simple enum: | A simple enum: | ||
<code php> | <code php> | ||
Line 26: | Line 42: | ||
</ | </ | ||
- | A binary enum: | + | A binary enum is used to represent a set of values: |
<code php> | <code php> | ||
binary enum FileMode { | binary enum FileMode { | ||
Line 33: | Line 49: | ||
Execute = 1 << 2, | Execute = 1 << 2, | ||
ReadWrite = Read | Write, | ReadWrite = Read | Write, | ||
+ | } | ||
+ | |||
+ | $foo = FileMode:: | ||
+ | </ | ||
+ | |||
+ | Both enum types can extend other enums: | ||
+ | <code php> | ||
+ | enum A { foo = 1 } | ||
+ | |||
+ | enum B extends A { bar = 2 } | ||
+ | |||
+ | $x = B::foo; | ||
+ | </ | ||
+ | |||
+ | Overriding constants from base enums is not allowed: | ||
+ | <code php> | ||
+ | enum C extends A { | ||
+ | foo = 3 // CompileError | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Constants must be '' | ||
+ | <code php> | ||
+ | enum foo { | ||
+ | bar = 2 ** 100, // CompileError | ||
+ | baz = 1.5 // CompileError | ||
+ | } | ||
+ | |||
+ | $x = 'this is a string'; | ||
+ | $y = (foo)$x; // TypeError | ||
+ | </ | ||
+ | |||
+ | ==== Type coercion and casts ==== | ||
+ | Enums are implicitly coercible to bool and string: | ||
+ | <code php> | ||
+ | function f(FileMode $mode) { | ||
+ | if ($mode) { | ||
+ | echo "mode: $mode"; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | f(FileMode:: | ||
+ | </ | ||
+ | |||
+ | Enum types can be explicitly cast to each other and '' | ||
+ | <code php> | ||
+ | $foo = (FileMode)123; | ||
+ | $bar = SomeEnum:: | ||
+ | $foo = (FileMode)$bar; | ||
+ | </ | ||
+ | |||
+ | Conversion from other types is not checked, thus enums can hold values not covered by their constants. '' | ||
+ | |||
+ | ==== Enum operations ==== | ||
+ | Enums are immutable and don't support arithmetic operations: | ||
+ | <code php> | ||
+ | $foo = FileMode:: | ||
+ | $foo = FileMode:: | ||
+ | $foo += 1; // TypeError | ||
+ | $bar = $foo + 1; // TypeError | ||
+ | </ | ||
+ | |||
+ | However, binary enums support bitwise operations: | ||
+ | <code php> | ||
+ | $foo = FileMode:: | ||
+ | $foo |= FileMode:: | ||
+ | $foo &= ~FileMode:: | ||
+ | </ | ||
+ | |||
+ | ==== Enum usage ==== | ||
+ | Concrete enum types can be used as typehints: | ||
+ | <code php> | ||
+ | function open(string $filename, FileMode $mode) | ||
+ | </ | ||
+ | However, not the enum keyword itself: | ||
+ | <code php> | ||
+ | function open(string $filename, enum $mode) // CompileError | ||
+ | </ | ||
+ | |||
+ | When the type is clear from typehints, enum name can be omitted: | ||
+ | <code php> | ||
+ | open(' | ||
+ | </ | ||
+ | is equivalent to: | ||
+ | <code php> | ||
+ | open(' | ||
+ | </ | ||
+ | |||
+ | Same for '' | ||
+ | <code php> | ||
+ | function f(Letters $x) { | ||
+ | switch ($x) { | ||
+ | case a: | ||
+ | // ... | ||
+ | case b: | ||
+ | // ... | ||
+ | } | ||
} | } | ||
</ | </ | ||
- | === Enums are classes | + | ==== Internal representation ==== |
- | Internally, enums are classes and enum constants are public class constants. This makes them the fourth OOP-ey type in PHP, along with `class`, `interface` and `trait`. They can be autoloaded just like the former types. All enums inherit from this base class (here is PHP pseudocode): | + | Internally, enums are classes and enum constants are public class constants. This makes them the fourth OOP-ey type in PHP, along with '' |
<code php> | <code php> | ||
- | final // In the sense that userspace can' | + | final // In the sense that userspace can' |
class Enum { | class Enum { | ||
private int $value; | private int $value; | ||
private function __construct(); | private function __construct(); | ||
- | public function isBinary() : bool; | + | public function isBinary(): bool; |
public function __toString(): | public function __toString(): | ||
return (string)(int)$this-> | return (string)(int)$this-> | ||
} | } | ||
+ | | ||
// Whether the current value is represented by one of this enum's constants | // Whether the current value is represented by one of this enum's constants | ||
// or their combination for binary enums | // or their combination for binary enums | ||
- | public function isKnownValue() : bool; | + | public function isKnownValue(): |
+ | |||
+ | // Returns a human readable representation of this enum's value | ||
+ | // e.g. (FileMode:: | ||
+ | // For unrecognized values, returns a decimal (simple enums) or hexadecimal (binary enums) string. | ||
+ | public function toHumanReadableString(): | ||
+ | |||
+ | public static function parse(string $enum) : ? | ||
} | } | ||
</ | </ | ||
+ | ===== Conventions used in this document ===== | ||
+ | Currently, PascalCase is used in enums due to author' | ||
+ | |||
+ | Same applies to the '' | ||
===== Backwards Incompatible Changes ===== | ===== Backwards Incompatible Changes ===== | ||
- | `enum` and `binary` will become reserved keywords. Class name `Enum` will become unavailable. | + | '' |
===== Proposed PHP Version(s) ===== | ===== Proposed PHP Version(s) ===== | ||
- | Next PHP 8.x (8.1?) | + | PHP 8.1? |
===== Open Issues ===== | ===== Open Issues ===== | ||
Make sure there are no open issues when the vote starts! | Make sure there are no open issues when the vote starts! | ||
+ | |||
+ | * Naming conventions | ||
+ | * Base class name(s) | ||
+ | * Type coercion details? | ||
===== Unaffected PHP Functionality ===== | ===== Unaffected PHP Functionality ===== | ||
Line 69: | Line 198: | ||
===== Future Scope ===== | ===== Future Scope ===== | ||
- | This section details areas where the feature might be improved in future, but that are not currently proposed in this RFC. | + | After this RFC is implemented, |
===== Proposed Voting Choices ===== | ===== Proposed Voting Choices ===== | ||
- | * Accept this RFC (yes / no)? | + | |
- | * What should be Enum fully qualified name (\Enum / \PHP\Enum)? | + | * What should be enum base class fully qualified name ('' |
+ | * What enum constant naming convention should be used (PascalCase / camelCase / UPPER_UNDERSCORED)? | ||
===== Patches and Tests ===== | ===== Patches and Tests ===== | ||
Line 93: | Line 223: | ||
===== References ===== | ===== References ===== | ||
Links to external references, discussions or RFCs | Links to external references, discussions or RFCs | ||
- | * https:// | + | * https:// |
===== Rejected Features ===== | ===== Rejected Features ===== | ||
Keep this updated with features that were discussed on the mail lists. | Keep this updated with features that were discussed on the mail lists. |
rfc/enum_v2.1589467523.txt.gz · Last modified: 2020/05/14 14:45 by maxsem