On Fri, Sep 24, 2004 at 01:17:40PM +0900, hammett wrote:
> I'm pretty new to Ruby and I'm looking for an enum-like-type just to make my
> code more readeable, but maybe I'm taking a wrong approach (badly influenced
> bu others languages I know, no names please :-)) and going against some ruby
> pragmatic principles, don't know.
> Anyway, if you do know something in the language that might help to
> accomplish modeling enums like the example below, in a more clever way, I'll
> appreciate the tip.

One way is to use module constants:

  module DaysOfWeek
    Sunday=0
    Monday=1
    Tuesday=2
    Wednesday=3
    Thursday=4
    Friday=5
    Saturday=6
    TO_S = { 0=>"Sunday", 1=>"Monday", }  # etc
  end

  a = DaysOfWeek::Sunday
  p DaysOfWeek::TO_S[a]   # not very pretty

It feels a bit too much like C, doesn't it :-) But it's simple and
efficient, especially if the numeric values are useful for ordering.

But since modules and classes are themselves constants, you can use them for
a more intelligent form of enum:

  module DaysOfWeek
    class Sunday; def self.to_s; "Sunday"; end; end
    class Monday; def self.to_s; "Monday"; end; end
    # etc
  end

  a = DaysOfWeek::Sunday  # a is a Class
  p a.to_s                # that's nice

You can compare a == DaysOfWeek::Sunday, but unfortunately not with === (so
it's doesn't sit well with case statements)

Another way is to have one object instance to represent each day of the
week:

  class DaysOfWeek
    def initialize(c,s)
      @day = c
      @str = s
    end
    def to_s
      @str
    end
  end
  class DaysOfWeek
    Sunday = self.new(0,'Sunday')
    Monday = self.new(1,'Monday')
    # etc
  end

  a = DaysOfWeek::Sunday   # a is a DaysOfWeek
  p a.to_s

If the constants have a logical ordering, then this lets you make use of it:

  class DaysOfWeek
    include Comparable
    attr_reader :day
    def <=>(other)
      @day <=> other.day
    end
  end

  p DaysOfWeek::Sunday < DaysOfWeek::Monday  # => true

Note that Sunday is still a constant, refering to a single instance of
DaysOfWeek; we are not creating a fresh object every time we use Sunday
anywhere. So statements like

   a = DaysOfWeek::Sunday
   puts "How are you?" if b == DaysOfWeek::Monday

should still be reasonably efficient.

Regards,

Brian.