On 28/08/05, David Brady <ruby_talk / shinybit.com> wrote: > 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? > Simply expanding on your thoughts: --------8<--------8<-------- module RATING RatingData = Struct.new(:name, :threshold, :description) class RatingData include Comparable def <=>(o) if o.respond_to?:threshold self.threshold <=> o.threshold else self.threshold <=> o end end end GOOD = RatingData.new( :Good, 0.8, "Good Rating" ) FAIR = RatingData.new( :Fair, 0.5, "Fair Rating" ) POOR = RatingData.new( :Poor, 0.2, "Poor Rating" ) end rating = RATING::POOR puts "Analysis: #{rating.description}" puts "*** Warning: Rating below Fair ***" if rating < RATING::FAIR --------8<--------8<-------- would be a possibility. Throw in some metaprogramming and it can get really nice. regards, Brian -- http://ruby.brian-schroeder.de/ Stringed instrument chords: http://chordlist.brian-schroeder.de/