From: Patrick Hurley Date: 2006-04-14T06:22:59+09:00 Subject: Re: Rubyesque way to do multiple <=> On 4/13/06, Victor Shepelev wrote: > > > I have class with some fields > > > > > > class Human > > > attr_accessor :sex, :age, :second_name, :first_name > > > end > > > > > > now I want to sort objects of this class. I've defined operator <=> > > > > > > class Human > > > def <=>(other) > > > [sex, age, second_name, first_name] <=> [sex, age, second_name, > > > first_name] > > > end > > > end > > > > > > Looks good, yeah? But! If I use third-party complex comparator for some > > of > > > the fields, I receive something like: > > > > > > def <=> (other) > > > res = ComplexCustomComparator.compare(sex, other.sex) > > > return res if res != 0 > > > > > > #if they have the same sex, do other comparisons > > > end > > > > > > Foooooo! > > > > > > How can I do the former in more elegant way? > > > > > > Thanks. > > > > > > Victor. > > > > Actually you just use your first version of method <=> without worrying > > about the second. > > Run the following code and you will clearly see why ;) > > ------------------8<------------------------------- > > class A > > def <=>(other) > > puts "<=> in A" > > 0 > > end > > end > > > > puts "If at first you do not succeed" > > [1, A.new] <=> [2, A.new] > > puts "..." > > [A.new ] <=> [A.new] > > ----------------------->8---------------------------- > > > > Ruby takes care of everything for you > > You haven't got it. I already USED first version, but I CAN'T if comparison > is done through stand-alone function instead of <=> > > > Cheers > > Robert > > Victor. > > > Can you provide a <=> for the special cases? Otherwise I guess something like this: class Array def fancy_cmp(other, sym = :<=>) each_with_index do |val,i| result = val.send(sym, other[i]) return result unless result.zero? end self.size <=> other.size end end Might help pth