Re: enum flag backed enum
| From: | Rowan Tommins [IMSoP] | Date: | Sat, 06 Sep 2025 11:48:19 +0000 |
| Subject: | Re: enum flag backed enum | ||
| References: | 1 2 3 4 5 6 7 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-128648@lists.php.net to get a copy of this message | ||
On 6 September 2025 01:47:35 BST, Rob Landers <rob@bottled.codes> wrote:
>
>Interesting... but we don’t really have a way to say that a parameter or return value must
>satisfy *any* constraints except that it be of a certain type. Hmmm, I guess we have
>"true" and "false" as values that can be returned/accepted by functions — but
>I think they’re the only ones.
Declaring an enum already declares a type. I wasn't thinking about constraining on lists of
values, just saying that something should be a "set of T" where T is the enum type.
Relying on integer ops, the result ends up as an int:
enum FooOption: flag { ... }
class Foo {
..
function setOption(FooOption $opt): void { ... }
function getCurrentOptions(): int { ... }
}
With general-purpose generics, you can make that strongly typed:
enum FooOption { ... }
class Foo {
..
function setOption(FooOption $opt): void { ... }
function getCurrentOptions(): Set<FooOption> { ... }
}
A specific EnumBitSet<T> could implement the integer serialisation:
class EnumBitSet<T> extends Set<T> {
function asBitMask(): int { ... }
}
enum FooOption: int { ... }
class Foo {
..
function setOption(FooOption $opt): void { ... }
function getCurrentOptions(): EnumBitSet<FooOption> { ... }
}
$foo = new Foo;
..
$foo->getCurrentOptions()->asBitMask();
With the recently proposed declare-time generics, you'd just need an extra declaration
alongside your enum:
class EnumBitSet<T> extends Set<T> {
function asBitMask(): int { ... }
}
enum FooOption: int { ... }
class FooOptionSet extends EnumSet<FooOption> {
// Can add additional methods here, but don't need to
}
class Foo {
..
function setOption(FooOption $opt): void { ... }
function getCurrentOptions(): FooOptionSet { ... }
}
$foo = new Foo;
..
$foo->getCurrentOptions()->asBitMask();
All the operator overloads or methods for things like intersect, union, contains, etc could be on
the top-level Set<T>, since they don't intrinsically have anything to do with enums.
That's the joy of our enum implementation being object-based: any algorithm that works on
object identity automatically works on enum cases.
Rowan Tommins
[IMSoP]