Skip to content

Conversation

@sampersand
Copy link
Contributor

@sampersand sampersand commented Nov 4, 2025

This PR adds in the Comparable::_CompareToZero interface, which is the actual return type that Comparable expects <=> to return.

@sampersand sampersand changed the title [Comparable] Add in _CompareToZero [Comparable] Add in Comparable::_CompareToZero Nov 4, 2025
@ksss
Copy link
Collaborator

ksss commented Nov 5, 2025

I believe it should return Integer? because the document says,

returning a value less than 0, returning 0, or returning a value greater than 0

https://docs.ruby-lang.org/en/master/Comparable.html

Also, I cannot think of any specific problems that this change would solve.
Could you give me an example?

@sampersand
Copy link
Contributor Author

sampersand commented Nov 11, 2025

Yeah, the docs are correct—it actually checks the return valeu for ret < 0 and ret > 0.

While all of the stdlib returns an Integer (-1, 0, or 1), I believe Comparable was designed this way to let people do things like returning the diff between two Floats. For example:

class Kilometers
  include Comparable
  
  def initialize(value) = @value = value.to_f
  def to_f = @value
  def <=>(other) = @value - other.to_f
  # ...
end

p Kilometers.new(1.2) < Kilometers.new(3.4)

This doesn't typecheck under the current RBS signatures, but does work in Ruby

@ParadoxV5
Copy link
Contributor

  def <=>(other) = @value - other.to_f
  def <=>(other) = @value <=> other.to_f

The point is still valid: MyNumber would be a better example.

@sampersand
Copy link
Contributor Author

@ParadoxV5 this is actually the way that ruby 0.49 did it:

% ./fixed/ruby <<RUBY
class X
   include Comparable
   def <=>(r) "A" <=> r end
end

print(X.new() <=> "Q")
RUBY
-16

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants