Right now if we have:
enum Color
Red
Green
Blue
end
a bunch of methods are generated for the enum members so you can do:
color = Color::Red
color.red? # => true
color.green? # => true
color.blue? # => true
This was added to avoid having to write:
color == Color::Red
# vs.
color.red? # much easier to read and write!
Now that we have automatic casting of symbols into enums we can introduce an is? method to do the same. It's just a bit more typing:
color.is?(:red)
The advantages of doing this are:
:red or :Red if you prefer the latterBecause == and === is defined on all types you can't really do color == :red. Well, you can, but it will match the most general overload which returns false. No autocasting can be involved.
This is probably not very intuitive so I propose to do one of these things:
Enum#==(Symbol) and Symbol#==(Enum) that work by checking the downcase string representation of the enum and symbol.is? insteadI'm not sure which one I prefer. Maybe the second one is better because it guarantees efficient code... plus it would be uncommon to have code that deals with enums and symbols at the same time.
Looks good, and what about the opposite, would it be color.not?(:red)?
(I also secretly hope to change not_nil! to #not!(Nil) one day :smile: )
I'm stupid, we can use !color.is?(:red) :sweat_smile: , unless if we want a raising color.not!(:red)
I don't understand, though, wouldn't it just work like this?
enum A
X
def is?(other : A)
self == other
end
end
p! A::X.is?(:x) # => true
Then it's just a bit strange that it doesn't work specifically for operators, though it's the same approach:
enum A
X
def ==(other : A)
super
end
end
p! A::X.==(:x) # => false
Wouldn't need "checking the downcase string representation" then, if we can just rely on #6074
Aren't we loosing compile-time safety with this approach?
The problem is that a symbol doesn't match A and so the supertypes are looked up and == from Object is found and so it gives false, not leaving a chance for autocasting to kick off.
I'd really like enum vs symbol comparison to work somehow... the only way I can think of it right now is by harcoding the logic in the compiler.
a symbol doesn't match A
Yeah then what is it doing in my first example which actually works?
Yeah then what is it doing in my first example which actually works?
Which one?
I'd prefer to leave this as-is. Is there really a problem, in practice, with the current way?
One issue is #7084: Underscore representations of enum members can collide (Foo and FOO) for example. This wouldn't technically solve this, because the symbol representation is similarly affected. But it could be an option to have the symbol equal the constant name, in which #is? would be maybe easier to use than methods with uppercase first character.
@straight-shoota than having both would be preferable since the query methods are type safe whereas #is? check is not.
Why wouldn't #is? be type safe. I'm assuming it is.
Most helpful comment
I'd prefer to leave this as-is. Is there really a problem, in practice, with the current way?