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