Enumerated Types

As part of a solution, I wish the value of an attribute to be one of a
finite set of values, in other words I believe I want an 'enumerated
type'. I've look at the 'Enumerable' and 'Enumerator' class and they
appear to me to be unrelated to what I wish to achieve (correct me if
I'm wrong).

I could do the traditional method of named constants with integer
values but I can't help feeling that there must be a class or some
nice method of doing this. Any advice would be appreciated.

I believe there are enum classes in the RAA. If you do not want to use them, symbols come pretty close:

class YourClass
   YOUR_ENUM = [
     :old,
     :young,
     :unknown,
   ].freeze
end

HTH

Kind regards

  robert

···

On 03.02.2007 19:52, Dan Stevens (IAmAI) wrote:

As part of a solution, I wish the value of an attribute to be one of a
finite set of values, in other words I believe I want an 'enumerated
type'. I've look at the 'Enumerable' and 'Enumerator' class and they
appear to me to be unrelated to what I wish to achieve (correct me if
I'm wrong).

I could do the traditional method of named constants with integer
values but I can't help feeling that there must be a class or some
nice method of doing this. Any advice would be appreciated.

I picked up this snippet of code:

# -------+---------+---------+-------- + --------+---------+---------+---------+
# Add methods enum and bit_enum to the Object class, thus making it much
# easier and less error-prone to define a long list of constants in a
# class. This idea comes from Ara.T.Howard@noaa, in a posting to ruby-talk
# on August 2, 2005 (in reply to a question). These work very nicely with
# a word-list array as generated via %w(). Very clever!

···

On 2/3/07, Dan Stevens (IAmAI) <dan.stevens.iamai@gmail.com> wrote:

As part of a solution, I wish the value of an attribute to be one of a
finite set of values, in other words I believe I want an 'enumerated
type'. I've look at the 'Enumerable' and 'Enumerator' class and they
appear to me to be unrelated to what I wish to achieve (correct me if
I'm wrong).

I could do the traditional method of named constants with integer
values but I can't help feeling that there must be a class or some
nice method of doing this. Any advice would be appreciated.

#
class Object
    def enum_constants(*list)
  mc = Module === self ? self : self.class
  list.flatten.each_with_index{|e, i| mc.const_set e.to_s.intern, i}
    end
    def enum_bit_constants(*list)
  mc = Module === self ? self : self.class
  list.flatten.each_with_index{|e, i| mc.const_set e.to_s.intern, 2 ** i}
    end
end
# -------+---------+---------+-------- + --------+---------+---------+---------+

An example of using it:

    # Constants that define all categories of packets which we recognize.
    enum_constants %w(
    SBC_NONE SBC_ARRAY SBC_NONUSER SBC_NO_IDSTR
    SBC_IGNFAIL SBC_ALL
    SBC_UNMATCHED )

The difference between enum_constants() and enum_bit_constants is
that enum_constants will define the values as 1, 2, 3, 4, 5, etc, while
enum_bit_constants will define them as 1,2,4,8,16,32. You can 'or'
the enum_bit_constant values together, and each one is a separate
bit so it won't clobber any other bit constant.

If you are not used to the %w() method of quoting, note that you only
put the names you want in there. You do *not* separate them with
commas!

--
Garance Alistair Drosehn = drosihn@gmail.com
Senior Systems Programmer
Rensselaer Polytechnic Institute; Troy, NY; USA

It seems to me that I should simply be able to use symbols as values
for my enumerated types, like for example:

class Color

  def initialize(color)
    @color = color
  end

  def to_hex
    case @color
      when :red: 0xFF0000
      when :green: 0x00FF00
      when :blue: 0x0000FF
      else @color
    end
  end

end

c = Color.new(:red)
puts c.to_hex.to_s(16)

Might there be any reason why I shouldn't do this, or am I quite fine
doing this?

···

On 03/02/07, Robert Klemme <shortcutter@googlemail.com> wrote:

On 03.02.2007 19:52, Dan Stevens (IAmAI) wrote:
> As part of a solution, I wish the value of an attribute to be one of a
> finite set of values, in other words I believe I want an 'enumerated
> type'. I've look at the 'Enumerable' and 'Enumerator' class and they
> appear to me to be unrelated to what I wish to achieve (correct me if
> I'm wrong).
>
> I could do the traditional method of named constants with integer
> values but I can't help feeling that there must be a class or some
> nice method of doing this. Any advice would be appreciated.

I believe there are enum classes in the RAA. If you do not want to use
them, symbols come pretty close:

class YourClass
   YOUR_ENUM = [
     :old,
     :young,
     :unknown,
   ].freeze
end

HTH

Kind regards

        robert

It seems to me that I should simply be able to use symbols as values
for my enumerated types, like for example:

class Color

  def initialize(color)
    @color = color
  end

  def to_hex
    case @color
      when :red: 0xFF0000
      when :green: 0x00FF00
      when :blue: 0x0000FF
      else @color
    end
  end

end

c = Color.new(:red)
puts c.to_hex.to_s(16)

Might there be any reason why I shouldn't do this, or am I quite fine
doing this?

This is fine. You may want to use a hash to make life simpler though:
class Color
  HexValues = { :red => 0xFF0000, :green => 0x00FF00, :blue => 0x0000FF }
  def to_hex
     HexValues[@color] or @color
  end
end

···

On 2/5/07, Dan Stevens (IAmAI) <dan.stevens.iamai@gmail.com> wrote:

On 03/02/07, Robert Klemme <shortcutter@googlemail.com> wrote:

> On 03.02.2007 19:52, Dan Stevens (IAmAI) wrote:
> > As part of a solution, I wish the value of an attribute to be one of a
> > finite set of values, in other words I believe I want an 'enumerated
> > type'. I've look at the 'Enumerable' and 'Enumerator' class and they
> > appear to me to be unrelated to what I wish to achieve (correct me if
> > I'm wrong).
> >
> > I could do the traditional method of named constants with integer
> > values but I can't help feeling that there must be a class or some
> > nice method of doing this. Any advice would be appreciated.
>
> I believe there are enum classes in the RAA. If you do not want to use
> them, symbols come pretty close:
>
> class YourClass
> YOUR_ENUM = [
> :old,
> :young,
> :unknown,
> ].freeze
> end
>
> HTH
>
> Kind regards
>
> robert
>

That's perfectly ok. If you need your enums only for mapping then I'd probably do this:

Color = Struct.new :name do
   CODES = Hash.new {|h,k| k}.update(
     :red => 0xFF0000,
     :green => 0x00FF00
     # ...
   )

   def to_hex; CODES[name] end
end

irb(main):010:0> Color.new(:red).to_hex.to_s 16
=> "ff0000"

If you need more enum dependent behavior you might want put more complex objects into the hash instead of only Fixnums.

Kind regards

  robert

···

On 05.02.2007 20:54, Dan Stevens (IAmAI) wrote:

It seems to me that I should simply be able to use symbols as values
for my enumerated types, like for example:

class Color

def initialize(color)
   @color = color
end

def to_hex
   case @color
     when :red: 0xFF0000
     when :green: 0x00FF00
     when :blue: 0x0000FF
     else @color
   end
end

end

c = Color.new(:red)
puts c.to_hex.to_s(16)

Might there be any reason why I shouldn't do this, or am I quite fine
doing this?