Replying to myself again... If writing "loose" <=> methods really isn't okay, then it sure would be nice to have a fast sgn (or sign) method built-in to Numeric. Then I could write a "string" <=> method of the form (y - x).sgn I know that I can use "<=> 0" to compute the sign of a number, but Numeric has a native abs method, so it should have a native sgn method. In my opinion, abs without sgn is like quo without modulo or sin without asin. This was discussed recently (but didn't go anywhere) on ruby-talk: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/235566 David David Flanagan wrote: > I agree that the current documentation and implementation are not > inconsistent. Implicit in my question was a concern about efficiency. I > have been assuming that being allowed to write <=> methods that return > any number less than zero or any number greater than zero is more > efficient than having to include the extra code to "clamp" those values > to -1 and +1. > > A simple benchmark is included. It shows that it is about 25% faster to > write a "loose" <=> method than a "strict" <=> method. (But only if the > loose <=> method returns an Integer. If it returns a Float, then the > loose method is actually slower.) > > Anyway, it is this efficiency issue that is at the root of my question. > Given that Ruby's documentation is not always really detailed, I > wondered if the docs are really definitive here. If it is actually > legal to write a loose <=> method, it would be nice to know that! > > David > > Benchmark code follows: > class Slow > def initialize(x) > @x = x > end > > def value > @x > end > > def <=>(other) > y = other.value > if @x < y > -1 > elsif @x > y > 1 > else > 0 > end > end > end > > class Fast > def initialize(x) > @x = x > end > > def value > @x > end > > def <=>(other) > other.value - @x > end > end > > f = [] > s = [] > > 100000.times do > x = rand(100000) > f << Fast.new(x) > s << Slow.new(x) > end > > require 'benchmark' > include Benchmark > > bmbm(2) do |x| > x.report("Fast") { f.sort } > x.report("Slow") { s.sort } > end > > > ------------------------------------------------ > Here are the benchmark results on my aging Linux system: > > Rehearsal ---------------------------------------- > Fast 4.390000 0.000000 4.390000 ( 4.403584) > Slow 5.640000 0.020000 5.660000 ( 5.657363) > ------------------------------ total: 10.050000sec > > user system total real > Fast 4.020000 0.000000 4.020000 ( 4.025188) > Slow 5.500000 0.000000 5.500000 ( 5.503963) > > > > Marte Raphael Y. Soliza wrote: >> I think there's nothing wrong with the implementation and >> documentation. True, an erronous implementation of <=> will still work >> if this is the implementation, but if we use exact comparisons such as >> == -1, trichotomy might be broken. For example, if two comparable >> objects of the same class, say a and b, are compared, and a is neither >> less than, equal, nor greater than b, then what is the relationship of >> a to b? This will give us a hint that the implementation of <=> is >> incorrect, and that's good, but I believe it's better (and safer) to >> have a fallback. If we throw an error that results from <=> returning >> a value other than -1, 0, and 1, then it might have an impact to >> efficiency especially in sorting huge array of values because we added >> an overhead of checking if the value returned is correct. >> >> On 4/1/07, *David Flanagan* <david / davidflanagan.com >> <mailto:david / davidflanagan.com>> wrote: >> >> Replying to my own post... >> >> Let me add that the existing numeric <=> operators all do appear to >> strictly return -1, 0, or +1. That is, they don't simply return >> y-x to >> compute a value less than, equal to, or greater than zero. This >> would >> argue that the current documentation of Comparable is correct, but >> that >> the implementation is written so that it works even for broken <=> >> operators. >> >> Anyway, I should say that it was probably presumptuous of me to >> assume >> that the documentation is incorrect. Everything I've seen in writing >> says that <=> must return -1,0, or +1. The implementation in >> compar.c >> makes it appear that this is not the case, however. I was not able to >> find any discussion of the return value of <=> in the ruby-talk >> archives... >> >> >> >> -- >> "Life is unfair... but beautiful." >> Scarlette Krimson > >