enum's can be outside Enum options?

194 views
Skip to first unread message

Roger Pack

unread,
Apr 26, 2017, 1:00:29 PM4/26/17
to Crystal
Question on enums, in this example in the docs, it seems to imply that a magic "unknown color" could occur, even if all the colors are in the Case statement, is that possible?
Thanks.
-roger-

def paint(color : Color)
  case color
  when Color::Red
    # ...
  else
    # Unusual, but still can happen
    raise "unknown color: #{color}"
  end
end

paint Color::Red

Luis Lavena

unread,
Apr 26, 2017, 9:50:01 PM4/26/17
to Crystal
Hello,


On Wednesday, April 26, 2017 at 2:00:29 PM UTC-3, Roger Pack wrote:
Question on enums, in this example in the docs, it seems to imply that a magic "unknown color" could occur, even if all the colors are in the Case statement, is that possible?

An unknown Color can occur if Color.new is used with an integer value, as described in the documentation:


enum Color
  Red   # 0
  Green # 1
  Blue  # 2
end

a = Color.new(1)
pp typeof(a) # => Color

b = Color.new(10)
pp typeof(b) # => Color

You can also use .color? helpers instead of usage of the enum constants:
 
enum Color
  Red   # 0
  Green # 1
  Blue  # 2
end

def paint(color : Color)
  case color
  when .red?
    puts "Red!"
  when .blue?
    puts "Blue!"
  when .green?
    puts "Green!"
  else
    puts "No idea!"
  end
end

paint Color::Red    # Red!
paint Color.new(10) # No idea!

Hope that helps

Cheers,
--
Luis Lavena

Roger Pack

unread,
Apr 28, 2017, 2:15:46 PM4/28/17
to crysta...@googlegroups.com
On Wed, Apr 26, 2017 at 7:50 PM, Luis Lavena <luisl...@gmail.com> wrote:
> Hello,
>
> On Wednesday, April 26, 2017 at 2:00:29 PM UTC-3, Roger Pack wrote:
>>
>> Question on enums, in this example in the docs, it seems to imply that a
>> magic "unknown color" could occur, even if all the colors are in the Case
>> statement, is that possible?
>
>
> An unknown Color can occur if Color.new is used with an integer value, as
> described in the documentation:
>
> https://crystal-lang.org/api/0.22.0/Enum.html

OK thank you.

"Values that don't correspond to an enum's constants are allowed:"

Hmm just debating this...in such a strongly typed language as Crystal
I might suggest this behavior (unknown enums) be made
optional...typically, users of an Enum for parameter passing don't
even know/want to to know what the integer values backing each
constant are. They just want to use the constant. And if only values
that correspond to constants are allowed, then case statements for
Enum's wouldn't "practically all" have to have that ending else block
(plus then the compiler could warn more easily "you missed one in that
case statement" or what not).
Anyway just my $0.02 :)

Next question: Is there a way in Crystal to import constants?

My use case is that I want to create a parameter for a method of a
class, but specifying and using an Enum seems to require multiple
constant derefs, here:

class Y
enum MethodOption
Red
end
def method(c : MethodOption)
puts "got #{c}"
end
end

a = Y.new
a.method(Y:: MethodOption::Red) # is there any way to say just "Red"
here, and it work?

Thanks all. :)
-roger-
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "Crystal" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/crystal-lang/YJbUG1lQP3Q/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> crystal-lang...@googlegroups.com.
> To post to this group, send email to crysta...@googlegroups.com.
> Visit this group at https://groups.google.com/group/crystal-lang.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/crystal-lang/7162a9fe-0aa0-43c4-97e5-02296df95a21%40googlegroups.com.
>
> For more options, visit https://groups.google.com/d/optout.

Luis Lavena

unread,
Apr 28, 2017, 3:16:26 PM4/28/17
to Crystal
On Friday, April 28, 2017 at 3:15:46 PM UTC-3, Roger Pack wrote:

"Values that don't correspond to an enum's constants are allowed:"

Hmm just debating this...in such a strongly typed language as Crystal
I might suggest this behavior (unknown enums) be made
optional...typically, users of an Enum for parameter passing don't
even know/want to to know what the integer values backing each
constant are.  They just want to use the constant.  And if only values
that correspond to constants are allowed, then case statements for
Enum's wouldn't "practically all" have to have that ending else block
(plus then the compiler could warn more easily "you missed one in that
case statement" or what not).
Anyway just my $0.02 :)


If you want to enforce, use `from_value` and `from_value?` instead of `.new`:


 
Next question: Is there a way in Crystal to import constants?

My use case is that I want to create a parameter for a method of a
class, but specifying and using an Enum seems to require multiple
constant derefs, here:

class Y
  enum MethodOption
     Red
   end
  def method(c : MethodOption)
    puts "got #{c}"
  end
end

a = Y.new
a.method(Y:: MethodOption::Red) # is there any way to say just "Red"
here, and it work?


You could use `Enum.parse` with a string, but I would recommend against that. If the Enum is expected to be used from the outside, I would recommend not placing it within the class itself.

Cheers,
--
Luis Lavena
 

Tim Uckun

unread,
Apr 29, 2017, 6:48:43 PM4/29/17
to crysta...@googlegroups.com
Parse of great (btw it should also support symbols) but it's a runtime thing. It would be nicer if it was handled compile time. 

When we declare the function we state we need an enum when we pass in we just send a constant. 



--
You received this message because you are subscribed to the Google Groups "Crystal" group.
To unsubscribe from this group and stop receiving emails from it, send an email to crystal-lang...@googlegroups.com.

To post to this group, send email to crysta...@googlegroups.com.
Visit this group at https://groups.google.com/group/crystal-lang.

Roger Pack

unread,
May 30, 2018, 9:15:03 AM5/30/18
to Crystal
OK I did figure out one hacky way (maybe not always recommended, but not but at least possible if desired):

appears it's not possible to "import" a constant, like

class Y
  X = OtherClass::OtherEnum
 end

but you can pull them in one at a time if desired, feels like an import anyway:

class Y
   SomeValue = OtherClass::OtherEnum::SomeValue
 end

full example:

class Y 
  enum MethodOption 
     Red, Green 
   end 
  def method(c : MethodOption) 
    puts "got #{c}" 
  end 
end 

class Z
  Red = Y::MethodOption::Red
  def method2
    a = Y.new 
    a.method(Red)
  end
end

Z.new.method2


I was also pleased to see it's possible to "kind of" import method as well:

All in the name of making us java/python devs happier :)

Roger Pack

unread,
Dec 8, 2019, 1:02:56 AM12/8/19
to Crystal
And another way, which I didn't know of till now, so for completeness... :)
alias, ex;


90:    alias Options = LibSSL::Options
Reply all
Reply to author
Forward
0 new messages