Where is Comparable <=> implemented?

187 Views Asked by At

I'm reading Comparable module.

And trying to see where Comparable module itself is implemented, but I can’t find it anywhere. I only see places where it gets added using include.

Isn't that the module should have its implementation provided elsewhere? So that you just do a plug and play by using include?

Or is that in the following code:

class Geeksforgeeks
      
# include comparable module
include Comparable
attr :name
      
    def <=>(other_name) # LineA
        name.length <=> other_name.name.length # LineB
    end
      
    def initialize(name)
        @name = name
    end
end

LineA: is something at the Geeksforgeeks class level.

LineB: is something at Integer (Length) level.

If that's the case then where is <=> written for Integers?

EDIT:

My code builds without include Comparable. I'm just not so sure what it means though:

class Geeksforgeeks
    
# does not include Comparable
attr :name
        
    def <=>(other_name) # LineA
        name.length <=> other_name.name.length # LineB
    end
        
    def initialize(name)
        @name = name
    end
end

jack = Geeksforgeeks.new('jack')
pete = Geeksforgeeks.new('pete')
alexander = Geeksforgeeks.new('Alexander')

def areSameGeeks(g1, g2)
    if g1 <=> g2
        puts 'equal'
    else 
        puts 'not equal'
    end
end

areSameGeeks(jack,pete) # equal
areSameGeeks(jack, jack) # equal
areSameGeeks(jack, alexander) # equal

Like why are all three, returning 'equal'?

3

There are 3 best solutions below

0
Stefan On BEST ANSWER

An example might help to understand how Comparable works:

module MyComparable
  def ==(other)
    (self <=> other) == 0
  end

  def <(other)
    (self <=> other) < 0
  end

  def >(other)
    (self <=> other) > 0
  end
end

The above module defines the methods ==, < and >. Their implementations rely on another method <=> which isn't defined by the module.

To actually use the module's methods, the including class has to provide this <=> in a meaningful way, e.g.:

class Foo
  include MyComparable   # <- this adds its instance methods to Foo

  attr_reader :name

  def initialize(name)
    @name = name
  end

  def <=>(other)
    name.length <=> other.name.length
  end
end

This gives us:

Foo.new("abc") == Foo.new("123")  #=> true
Foo.new("abc") == Foo.new("1234") #=> false
Foo.new("abc") <  Foo.new("1234") #=> true

== and < are from MyComparable, but it only works because of Foo#<=>.

A similar approach is taken by Enumerable which requires an each method to be implemented by the including class.

1
Leon On

<=> isn't implemented within the Comparable module:

https://ruby-doc.org/core-3.1.1/Comparable.html

This operation is implemented within each Ruby type (for example - String, Array, Integer). For default Ruby types it is possible to compare only objects of the same type, if you will try to compare it with something different you will get the nil value.

In your example LineA is a method for objects of Geeksforgeeks class, so you can use it as gfg_object <=> other_gfg_object. By the way your implementation of <=> isn't quite correct, it should checks that other_name is an instance of Geekforgeeks class (or another type) and return nil if it isn't. Correct example:

    def <=>(object)
        if object.is_a? Geekforgeeks
            return name.length <=> object.name.length
        elsif object.is_a? String
            return name.length <=>object.length
        else 
            return nil
        end
    end
1
Jörg W Mittag On

And trying to see where Comparable module itself is implemented, but I can’t find it anywhere.

Comparable is part of the core library of whatever Ruby implementation you are using. For example:

However, I personally find it not so much interesting where something is implemented but rather where it is specified. Comparable is specified in section 15.3.3 Comparable of the ISO/IEC 30170:2012 Information technology — Programming languages — Ruby specification. A less formal specification is given in core/comparable/ of The Ruby Spec Suite aka ruby/spec.

It is also described in The Ruby Programming Language by David Flanagan and Yukihiro 'matz' Matsumoto, Programming Ruby by Dave Thomas, Andy Hunt, and Chad Fowler, and of course in the Ruby documentation

If that's the case then where is <=> written for Integers?

Integer#<=> is part of the core library of whatever Ruby implementation you are using. For example:

However, I personally find it not so much interesting where something is implemented but rather where it is specified. Integer#<=> is specified in section 15.2.8.3.6 Integer#<=> of the ISO/IEC 30170:2012 Information technology — Programming languages — Ruby specification. A less formal specification is given in core/integer/comparison_spec.rb of The Ruby Spec Suite aka ruby/spec.

It is also described in The Ruby Programming Language by David Flanagan and Yukihiro 'matz' Matsumoto, Programming Ruby by Dave Thomas, Andy Hunt, and Chad Fowler, and of course in the Ruby documentation.