Re: Ruby idiom for enum?



David Brady wrote:

In C++, I would use an enum for each of the values, then build arrays of floats and strings indexed by those enums to hold the thresholds and descriptions.

That's also possible in Ruby, but I think it is a better idea to aggregate all the data into the enum member itself.


Here's Ruby code for doing C++ style enums:

# Represents a C# style enumeration of known values.
#
# Usage:
#   Color = Enum.new(:Red, :Green, :Blue)
#   Color.is_a?(Enum) # => true
#   Color::Red.inspect # => "Color::Red"
#   Color::Green.is_a?(Color) # => true
#   Color::Green.is_a?(Enum::Member) # => true
#   Color::Green.index # => 1
#   Color::Blue.enum # => Color
#   values = [[255, 0, 0], [0, 255, 0], [0, 0, 255]]
#   values[Color::Green] # => [0, 255, 0]
#   Color[0] # => Color::Red
#   Color.size # => 3
#
# Enums are enumerable. Enum::Members are comparable.
class Enum < Module
  class Member < Module
    attr_reader :enum, :index

    def initialize(enum, index)
      @enum, @index = enum, index
      # Allow Color::Red.is_a?(Color)
      extend enum
    end

    # Allow use of enum members as array indices
    alias :to_int :index
    alias :to_i :index

    # Allow comparison by index
    def <=>(other)
      @index <=> other.index
    end

    include Comparable
  end

  def initialize(*symbols, &block)
    @members = []
    symbols.each_with_index do |symbol, index|
      # Allow Enum.new(:foo)
      symbol = symbol.to_s.sub(/^[a-z]/) { |letter| letter.upcase }.to_sym
      member = Enum::Member.new(self, index)
      const_set(symbol, member)
      @members << member
    end
    super(&block)
  end

  def [](index) @members[index] end
  def size() @members.size end
  alias :length :size

  def first(*args) @members.first(*args) end
  def last(*args) @members.last(*args) end

  def each(&block) @members.each(&block) end
  include Enumerable
end

But I think it is not the best match in this case.

Struct.new("RatingData", name, threshold, description)

RATING_GOOD = Struct::RatingData( :Good, 0.8, "Good Rating" )
RATING_FAIR = Struct::RatingData( :Fair, 0.5, "Fair Rating" )

This sounds good, but I'd go with a module:

module Rating
  Good = Struct::RatingData.new(:Good, 0.8, "Good Rating")
  Fair = Struct::RatingData.new(:Fair, 0.5, "Fair Rating")
end

That seems more Rubyish to me.



.



Relevant Pages

  • [PATCH 05/15] drbd: user space interface (based upon connector/netlink)
    ... new file mode 100644 ... This file is part of DRBD by Philipp Reisner and Lars Ellenberg. ... +enum drbd_disconnect_p { ... +#define NL_INTEGER(pn, pr, member) ...
    (Linux-Kernel)
  • [PATCH 06/16] drbd: user space interface (based upon connector/netlink)
    ... new file mode 100644 ... This file is part of DRBD by Philipp Reisner and Lars Ellenberg. ... +enum drbd_disconnect_p { ... +#define NL_INTEGER(pn, pr, member) ...
    (Linux-Kernel)
  • Re: Case Change By Itself in VBA Code - Help
    ... I, too, have observed the behavior where Enum's members' case do not get preserved correctly whereas built-in Enum members can preserve the case. ... What would happen is in the declaration for the Enum, the dsrsPending member inherits the new case as I just typed. ...
    (microsoft.public.access.modulesdaovba)
  • Re: [Enum]
    ... Where can I find an explaination of the usage of in an Enum? ... what the brackets do is make that member of the Enum type hidden. ... Public Property Let SortType(ColumnIndex As Long, ... it's customary to use an underscore as the first character for the hidden enum member. ...
    (microsoft.public.vb.general.discussion)
  • Re: enum collection of constant values
    ... > def bit_enum ... > probably could also combine this idea with the Enum module... ... this is the first time I tried searching RAA or RubyForge for some ...
    (comp.lang.ruby)