[#23657] [Bug #1550] String#lstrip! raises RuntimeError on Frozen String Despite Making No Changes — Run Paint Run Run <redmine@...>

Bug #1550: String#lstrip! raises RuntimeError on Frozen String Despite Making No Changes

13 messages 2009/06/01

[#23729] [Bug #1583] Time + String no Longer Raises TypeError? — Run Paint Run Run <redmine@...>

Bug #1583: Time + String no Longer Raises TypeError?

14 messages 2009/06/05

[#23770] [Bug #1595] rake unusable on windows install — Robert Gonzalez <redmine@...>

Bug #1595: rake unusable on windows install

10 messages 2009/06/09

[#23869] [Bug #1640] [PATCH] Documentation for the Rational Class — Run Paint Run Run <redmine@...>

Bug #1640: [PATCH] Documentation for the Rational Class

12 messages 2009/06/16

[#23903] [Bug #1648] Rational#div Raises NoMethodError for Invalid Argument — Run Paint Run Run <redmine@...>

Bug #1648: Rational#div Raises NoMethodError for Invalid Argument

9 messages 2009/06/17

[#23977] [ANN] meeting log of RubyDeveloperKaigi20090622 — "Yugui (Yuki Sonoda)" <yugui@...>

Hi,

41 messages 2009/06/23
[#23979] Re: [ANN] meeting log of RubyDeveloperKaigi20090622 — Run Paint Run Run <runrun@...> 2009/06/23

Thanks for the update. :-)

[#24173] Re: [ANN] meeting log of RubyDeveloperKaigi20090622 — "NARUSE, Yui" <naruse@...> 2009/07/07

Sorry for late response,

[#24174] Re: [ANN] meeting log of RubyDeveloperKaigi20090622 — Luis Lavena <luislavena@...> 2009/07/07

On Tue, Jul 7, 2009 at 12:12 AM, NARUSE, Yui<[email protected]> wrote:

[#24242] Re: [ANN] meeting log of RubyDeveloperKaigi20090622 — Charles Oliver Nutter <headius@...> 2009/07/09

On Mon, Jul 6, 2009 at 10:18 PM, Luis Lavena<[email protected]> wrote:

[#24010] [Bug #1685] Some windows unicode path issues remain — B Kelly <redmine@...>

Bug #1685: Some windows unicode path issues remain

26 messages 2009/06/24
[#29189] [Bug #1685] Some windows unicode path issues remain — Yuki Sonoda <redmine@...> 2010/04/01

Issue #1685 has been updated by Yuki Sonoda.

[#29200] Re: [Bug #1685] Some windows unicode path issues remain — Bill Kelly <billk@...> 2010/04/01

Yuki Sonoda wrote:

[#29892] Re: [Bug #1685] Some windows unicode path issues remain — Bill Kelly <billk@...> 2010/04/29

Hi,

[#24058] [Bug #1696] http downloads are unuseably slow — Steven Hartland <redmine@...>

Bug #1696: http downloads are unuseably slow

19 messages 2009/06/27

[#24063] [Feature #1697] Object#<=> — Marc-Andre Lafortune <redmine@...>

Feature #1697: Object#<=>

15 messages 2009/06/28

[ruby-core:24063] [Feature #1697] Object#<=>

From: Marc-Andre Lafortune <redmine@...>
Date: 2009-06-28 01:48:45 UTC
List: ruby-core #24063
Feature #1697: Object#<=>
http://redmine.ruby-lang.org/issues/show/1697

Author: Marc-Andre Lafortune
Status: Open, Priority: Normal
Assigned to: Yukihiro Matsumoto, Category: core, Target version: 1.9.2

The definition of the <=> operator states:
"... And if the two operands are not comparable, it returns nil"  (The Ruby Programming Language, O'Reilly)

Attempting to compare objects, when one or both do not define the <=> operator, causes a NoMethodError to be raised. For example, "false <=> 0" raises in this way. This behavior is unexpected and runs counter to the principle defined above.

Further, "0 <=> false" returns nil. This is fundamentally inconsistent. The two comparisons are the other's converse, yet the raising of an exception in the first case implies that the programmer was in error; that the mere act of making this comparison was erroneous.

The solution is for Object to define a <=> operator. This will solve the case described above, along with the general case of comparing an object to another when one or both do not define <=>. Similarly to Time#<=>, it would return the converse of arg <=> self (i.e. nil => nil, num => -num). It needs to detect recursion, in which case it should return nil or 0 depending on the result of self == arg.

This change would make it always safe to call <=> without having to check first if it respond_to? :<=> (or rescuing NoMethodError).

The existence of Object#<=> would make it much easier for all programmers to define a good <=> operator for their classes. They can simply call super if they don't know how to handle some argument type. For example:

class MyClass
  include Comparable
  def <=> (arg)
    return super unless arg.is_a? MyClass
    # go on with comparison
  end
end

With this simple line, the developper has enabled other classes to be comparable with MyClass. No need to monkeypatch MyClass to ensure that comparing its objects with objects of class ComparableToMyClass will work. Without a 'super', implementing this becomes quite difficult and requires the use of recursion guards (which are not defined in the standard library).

Note that neither String#<=> nor Time#<=> currently use recursion guards, which is not robust and can lead to problems. For instance:

class MyClass
  include Comparable
  def <=> (arg)
    return -1 if arg.is_a? MyClass
    cmp = arg <=> self
    cmp ? -cmp : nil
  end
end

MyClass.new <=> Time.now
# ==> raises a SystemStackError

class Time
  alias_method :to_str, :to_s
end
"now" <=> Time.now
# ==> endless loop that can't be interrupted with ctrl-C.


In summary, defining Object#<=> would:
1) bring consistency between a <=> b and b <=> a
2) provide a sensible default (nil) for objects that can't be compared
3) make it easier for generic methods to call <=> (no rescue or :respond_to? needed)
4) make it much easier for developpers to write extensible <=> methods for their classes.


Side notes:

The proposition stands only for Object. BasicObject would still be available for developers preferring a class with a strict minimum of methods.

The only code that could break would have to be both checking respond_to? :<=> (or rescuing a NoMethodError) _and_ behaving differently than if the <=> method had returned nil. Such code would be quite nonsensical, given the definition of <=>

Other comparison operators like <, <=, >=, > would also gain in consistency if they were defined in terms of <=>. This way, 0 < nil and nil > 0 would raise the same errors instead of errors of different types. This is secondary to the main question: is it better to define Object#<=> or not?
My vote is on 'yes'.

(Thanks to the readers of my first draft)


----------------------------------------
http://redmine.ruby-lang.org

In This Thread

Prev Next