2005/8/28, David Brady <ruby_talk / shinybit.com>:
> Okay, one more question from a C++ leopard trying to change his spots:
> 
> I want to set up a program that uses some predefined values to determine
> its logic.  For example, a method could analyze some data and return
> "Good", "Fair", "Poor", or "Out of Bounds" based on a set of
> thresholds.  I want to be able to refer to these values by name in my
> code, so constants or symbols make a good choice here.  But I also want
> to build a sort of rule set around these values: some function returns
> values in the range of (0.0..1.0) and I want to be able to say that 0.8
> is the minimum score for "Good", etc.  I also want the word "Good"
> stored in a specific single place so that I don't make any typos each
> time I need to print the description.
> 
> 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.
> 
> What's the Ruby idiom for this?
> 
> Perhaps Struct followed by some initializer arrays?  This seems like a
> good start but I end up wanting to build a set of constants first to use
> as keys to a hash containing the Structs.  Perhaps the Structs should be
> the constants themselves, like:
> 
> Struct.new("RatingData", name, threshold, description)
> 
> RATING_GOOD = Struct::RatingData( :Good, 0.8, "Good Rating" )
> RATING_FAIR = Struct::RatingData( :Fair, 0.5, "Fair Rating" )
> 
> ...etc.  The analyze_data could return RATING_GOOD if things were fine.  So:
> 
> rating = analyze_data data
> puts "Analysis: #{rating.description}"
> 
> Though this doesn't let me treat the values as though they are ordered, e.g.
> 
> puts "*** Warning: Rating below Fair ***" if rating < RATING_FAIR
> 
> Thoughts?

There are several possible solutions: Use an enum lib maybe there's
something in the RAA
http://raa.ruby-lang.org/search.rhtml?search=enum

Or create a Hash with nested Arrays

RATINGS = {
  :good => [0.8, "Good Rating"],
  :bad => [0.1, "Bad Rating"]
}

I'd probably go with your struct approach with some additional code
for creation of a single rating that will also register all ratings
somewhere and with some algorithm for determining the rating.

For example, if you place your constants in class Struct::RatingData
you can easily get all ratings via Struct::RatingData.constants.

If you need efficient rating assignment from a float value and if
there are many ratings then you might want to store ratings ordered by
the threshold to use binary search on the ratings to find the correct
one.

Just some thoughts.

Kind regards

robert