Project

General

Profile

Actions

Feature #21157

closed

Comparison operator <>

Added by lpogic (Łukasz Pomietło) 13 days ago. Updated 6 days ago.

Status:
Feedback
Assignee:
-
Target version:
-
[ruby-core:121172]

Description

I propose introducing a comparison operator <> which would give the following results:

1 <> 2 # => -1
2 <> 1 # => 1
1 <> 1 # => false
1 <> "a" # => true

With the help of the new operator, complex ordering expressions could be written explicitly. For example:

Point = Struct.new(:x, :y)
array = [Point.new(1, 2), Point.new(6, 4), Point.new(2, 2), Point.new(5, 2)]

array.sort{|a, b| a.y <> b.y || b.x <> a.x || 0 } # => [#<struct Point x=5, y=2>, #<struct Point x=2, y=2>, #<struct Point x=1, y=2>, #<struct Point x=6, y=4>]

The <> notation may look familiar to sql users, where it means 'not equal'. Defined in the form given it will retain this meaning to some extent:

a = b = 1
a_not_equal_b if a <> b
a_equal_b unless a <> b

Updated by Hanmac (Hans Mackowiak) 13 days ago

Isn't it easier to use sort_by instead? And then use an Array as Sorting Field?

array.sort_by {|o| [o.y, -o.x] } #=> [#<struct Point x=5, y=2>, #<struct Point x=2, y=2>, #<struct Point x=1, y=2>, #<struct Point x=6, y=4>]

Updated by lpogic (Łukasz Pomietło) 13 days ago

I think that not having to create intermediate arrays and referencing the x coordinate when y is different would be an advantage.

Updated by P3t3rU5 (Pedro Miranda) 13 days ago

comparison operator already exists it's <=>

if you want a class to be comparable you just include the Comparable module and implement <=>

Updated by nobu (Nobuyoshi Nakada) 13 days ago

  • Description updated (diff)

lpogic (Łukasz Pomietło) wrote:

I propose introducing a comparison operator <> which would give the following results:

1 <> 2 # => -1
2 <> 1 # => 1
1 <> 1 # => false
1 <> "a" # => true

I'm not sure what the last example means, maybe incomparable -> true?

With the help of the new operator, complex ordering expressions could be written explicitly. For example:

Point = Struct.new(:x, :y)
array = [Point.new(1, 2), Point.new(6, 4), Point.new(2, 2), Point.new(5, 2)]

array.sort{|a, b| a.y <> b.y || b.x <> a.x || 0 } # => [#<struct Point x=5, y=2>, #<struct Point x=2, y=2>, #<struct Point x=1, y=2>, #<struct Point x=6, y=4>]
array.sort{|a, b| (a.y <=> b.y).nonzero? || b.x <> a.x}

I agree that it would be a bit shorter/simpler, but I doubt it's worth adding new syntax.

The <> notation may look familiar to sql users, where it means 'not equal'.

Or BASIC users?
Anyway, <> in SQL is a boolean operator and not expected returing ±1.

Updated by lpogic (Łukasz Pomietło) 13 days ago

P3t3rU5 (Pedro Miranda) wrote in #note-3:

comparison operator already exists it's <=>

if you want a class to be comparable you just include the Comparable module and implement <=>

<=> is good enough for comparing a single property, e.g. a.y <=> b.y. Things get complicated when we want to compare several consecutive properties, e.g.:

array.sort do |a, b|
  result = a.y <=> b.y
  result == 0 ? b.x <=> a.x : result
end

Including the Comparable module simply moves this code to a different location. And this is only an option if we want to sort in natural order.

Updated by lpogic (Łukasz Pomietło) 13 days ago

nobu (Nobuyoshi Nakada) wrote in #note-4:

I'm not sure what the last example means, maybe incomparable -> true?

Yes, this is a case where objects are incomparable. I'm not sure if true is the most appropriate value, but I don't have a better idea at the moment.

nobu (Nobuyoshi Nakada) wrote in #note-4:

array.sort{|a, b| (a.y <=> b.y).nonzero? || b.x <=> a.x}

This actually solves the presented problem in a relatively clear way. Until now I was not aware of the existence of nonzero?.

nobu (Nobuyoshi Nakada) wrote in #note-4:

Or BASIC users?
Anyway, <> in SQL is a boolean operator and not expected returing ±1.

Sure. I only see the similarity when <> is used in logical expressions.

Updated by Eregon (Benoit Daloze) 7 days ago

Let's not add new syntax and methods for something which can easily be done with nonzero? (and which is BTW the main purpose of nonzero?)

Updated by nobu (Nobuyoshi Nakada) 6 days ago

  • Status changed from Open to Feedback

Added a reference to Numeric#nonzero? at d31c15d81f368614f81e8c32295d0529b66e7334.
Isn't it enough?

Updated by lpogic (Łukasz Pomietło) 6 days ago · Edited

Such a note in the documentation would certainly be advisable. Could a similar one be added to the max, min and minmax methods?

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like1Like0Like0Like0