-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
allow to include enum #3310
Comments
I've thought about this many times, and it's a really nice feature. Maybe we should include this in the standard library: macro include_constants(type)
{% for constant in type.resolve.constants %}
{{constant}} = {{type}}::{{constant}}
{% end %}
end
enum Errors
ERROR1 = 1
ERROR2 = 2
end
include_constants Errors
p ERROR1 :-) |
I've also been keeping one of these (and it had to be named like that before the addition of private modules) |
It's interesting to consider whether the "included" constants should be documented (in my case they aren't). Maybe a configurable argument? And now that I think about it, maybe instead it makes more sense to just allow enums to expose their constants unqualified as a language feature, so there's a proper way to indicate that they're available outside without annoying lists of placeholders in documentation. |
I'll just throw in a few more or less daunting ideas here: It could be preferable if we had some "reverse inference" (I know I abuse that term ;-) ) matching literals, as has been discussed earlier, and for this case also unqualified enum-constants, which match towards Enums in ivars type declarations or a parameter's restriction, when explicitly an Enum. This is harder to do, but cause less name pollution and thus avoids possible conflicts, while still allowing much more clearly readable code. First, a Naive SuggestionIt can of course never be "fool proof" (just like with freevars contra types) and introduces further rules for order of matching methods: enum MyEnum
Red
Green
Purple
end
Green = 47
# To show of one problematic
def my-fun(x, y)
p "my-fun 1: #{x}, #{y}"
end
def my-fun(x, y : MyEnum)
p "my-fun 2: #{x}, #{y}"
end
my-fun 1, 2 # business as usual
my-fun 1, Red # Red not found, but a signature exists with enum, try matching in that. Match! Expand.
my-fun 1, Green # matches the const. Problematic Gotcha!!!
The gotcha alone, is a strong argument against. So How About Something Similar to Swift?Indicating a non qualified enum const explicitly: my-fun 1, 2 # business as usual
my-fun 1, .Red # Signature exists with enum, try matching them. Match! Expand to qualified.
my-fun 1, .Green # Of course also gives the expected result. The dot-const notation could of course prove problematic, unless parenthesis call is demanded when it's used as first arg (that's true already for some literals). However, do we ever access a const-like identifier like that?: some-fun .Red # how will the parser take this?
some-fun(.Red) # this is sure to be ok at least. And, the ivars of course: class Foo
@val : MyEnum = .None
def do_stuff
@val = .Purple
end
end Another option, is a |
@ozra, I had this idea but with the syntax... |
But then it's a symbol!? |
We actually looked at how this works in Swift and like it, and thought about doing something similar in Crystal :-) Our main issue is that Swift requires type declarations everywhere, while we don't, so in their case if you have And like @BlaXpirit says, for enums we though about using symbol literals, as this is also closer to Ruby, though a downside of that is that it adds more magic to the language (and we have to solve the conflict between symbol and enum). |
@ozra, it would normally be a symbol. I'm suggesting it only for the contexts where it couldn't possibly be a symbol and it's clear what enum is being referred to. |
👍 I can't wait for something like this. Compare: case opcode
when StandardOpcode::NegateStmt
when StandardOpcode::FixedAdvancedPc
end vs case opcode
when :negate_stmt
when :fixed_advance_pc
end Or In places where the type is known to be an enum, this would really help increase readability, without sacrificing type safety. |
@asterite I suspected you'd already thought about it XD I think it should try all overloads that match with an Enum in the position, and then try them to see which includes the const. Of course the problem is that several enums can have the same const. And then a rule is needed for signature precedence. Perhaps whichever enum is declared first or last in the program? |
with symbols you can typo and program compiled, with enums not. |
@kostya I assume the symbols would be transformed to their enums at compile time, and thus validated, this failing to compile with a typo. |
@ysbaddaden you can do https://play.crystal-lang.org/#/r/19y4 since #285 in order to short enum Color
Red
Green
Blue
end
color = Color::Red
a = case color
when .red?
1
when .green?
2
when .blue?
3
end
pp color
pp a |
How about not making them symbols? It seems confusing and magic to me. There should be some nonambiguous syntax, or no syntax. |
Agree with @RX14 fully. Symbols are symbols. Unqualified Enum consts another. |
We got |
this code not work
need to change enum to module, after that it works, may be allow to include enum also?
The text was updated successfully, but these errors were encountered: