[ruby-core:121172] [Ruby master Feature#21157] Comparison operator <>

Issue #21157 has been reported by lpogic (Łukasz Pomietło). ---------------------------------------- Feature #21157: Comparison operator <> https://bugs.ruby-lang.org/issues/21157 * Author: lpogic (Łukasz Pomietło) * Status: Open ---------------------------------------- I propose introducing a comparison operator *<>* which would give the following results: ```ruby 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: ```ruby 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: ```ruby a = b = 1 a_not_equal_b if a <> b a_equal_b unless a <> b ``` -- https://bugs.ruby-lang.org/

Issue #21157 has been updated by Hanmac (Hans Mackowiak). Isn't it easier to use sort_by instead? And then use an Array as Sorting Field? ```ruby 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>] ``` ---------------------------------------- Feature #21157: Comparison operator <> https://bugs.ruby-lang.org/issues/21157#change-112111 * Author: lpogic (Łukasz Pomietło) * Status: Open ---------------------------------------- I propose introducing a comparison operator *<>* which would give the following results: ```ruby 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: ```ruby 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: ```ruby a = b = 1 a_not_equal_b if a <> b a_equal_b unless a <> b ``` -- https://bugs.ruby-lang.org/

Issue #21157 has been updated by lpogic (Łukasz Pomietło). I think that not having to create intermediate arrays and referencing the x coordinate when y is different would be an advantage. ---------------------------------------- Feature #21157: Comparison operator <> https://bugs.ruby-lang.org/issues/21157#change-112112 * Author: lpogic (Łukasz Pomietło) * Status: Open ---------------------------------------- I propose introducing a comparison operator *<>* which would give the following results: ```ruby 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: ```ruby 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: ```ruby a = b = 1 a_not_equal_b if a <> b a_equal_b unless a <> b ``` -- https://bugs.ruby-lang.org/

Issue #21157 has been updated by P3t3rU5 (Pedro Miranda). comparison operator already exists it's `<=>` if you want a class to be comparable you just include the [Comparable module](https://docs.ruby-lang.org/en/master/Comparable.html) and implement `<=>` ---------------------------------------- Feature #21157: Comparison operator <> https://bugs.ruby-lang.org/issues/21157#change-112113 * Author: lpogic (Łukasz Pomietło) * Status: Open ---------------------------------------- I propose introducing a comparison operator *<>* which would give the following results: ```ruby 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: ```ruby 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: ```ruby a = b = 1 a_not_equal_b if a <> b a_equal_b unless a <> b ``` -- https://bugs.ruby-lang.org/

Issue #21157 has been updated by nobu (Nobuyoshi Nakada). Description updated lpogic (Łukasz Pomietło) wrote:
I propose introducing a comparison operator *<>* which would give the following results: ```ruby 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: ```ruby 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>] ```
```ruby 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. ---------------------------------------- Feature #21157: Comparison operator <> https://bugs.ruby-lang.org/issues/21157#change-112115 * Author: lpogic (Łukasz Pomietło) * Status: Open ---------------------------------------- I propose introducing a comparison operator *<>* which would give the following results: ```ruby 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: ```ruby 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: ```ruby a = b = 1 a_not_equal_b if a <> b a_equal_b unless a <> b ``` -- https://bugs.ruby-lang.org/

Issue #21157 has been updated by lpogic (Łukasz Pomietło). 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](https://docs.ruby-lang.org/en/master/Comparable.html) 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.: ```ruby 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. ---------------------------------------- Feature #21157: Comparison operator <> https://bugs.ruby-lang.org/issues/21157#change-112116 * Author: lpogic (Łukasz Pomietło) * Status: Open ---------------------------------------- I propose introducing a comparison operator *<>* which would give the following results: ```ruby 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: ```ruby 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: ```ruby a = b = 1 a_not_equal_b if a <> b a_equal_b unless a <> b ``` -- https://bugs.ruby-lang.org/

Issue #21157 has been updated by lpogic (Łukasz Pomietło). 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:
```ruby 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. ---------------------------------------- Feature #21157: Comparison operator <> https://bugs.ruby-lang.org/issues/21157#change-112118 * Author: lpogic (Łukasz Pomietło) * Status: Open ---------------------------------------- I propose introducing a comparison operator *<>* which would give the following results: ```ruby 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: ```ruby 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: ```ruby a = b = 1 a_not_equal_b if a <> b a_equal_b unless a <> b ``` -- https://bugs.ruby-lang.org/

Issue #21157 has been updated by nobu (Nobuyoshi Nakada). Tried an implementation: https://github.com/nobu/ruby/tree/ncmp ---------------------------------------- Feature #21157: Comparison operator <> https://bugs.ruby-lang.org/issues/21157#change-112119 * Author: lpogic (Łukasz Pomietło) * Status: Open ---------------------------------------- I propose introducing a comparison operator *<>* which would give the following results: ```ruby 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: ```ruby 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: ```ruby a = b = 1 a_not_equal_b if a <> b a_equal_b unless a <> b ``` -- https://bugs.ruby-lang.org/

Issue #21157 has been updated by Eregon (Benoit Daloze). 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?`) ---------------------------------------- Feature #21157: Comparison operator <> https://bugs.ruby-lang.org/issues/21157#change-112183 * Author: lpogic (Łukasz Pomietło) * Status: Open ---------------------------------------- I propose introducing a comparison operator *<>* which would give the following results: ```ruby 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: ```ruby 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: ```ruby a = b = 1 a_not_equal_b if a <> b a_equal_b unless a <> b ``` -- https://bugs.ruby-lang.org/

Issue #21157 has been updated by nobu (Nobuyoshi Nakada). Status changed from Open to Feedback Added a reference to `Numeric#nonzero?` at commit:d31c15d81f368614f81e8c32295d0529b66e7334. Isn't it enough? ---------------------------------------- Feature #21157: Comparison operator <> https://bugs.ruby-lang.org/issues/21157#change-112190 * Author: lpogic (Łukasz Pomietło) * Status: Feedback ---------------------------------------- I propose introducing a comparison operator *<>* which would give the following results: ```ruby 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: ```ruby 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: ```ruby a = b = 1 a_not_equal_b if a <> b a_equal_b unless a <> b ``` -- https://bugs.ruby-lang.org/

Issue #21157 has been updated by lpogic (Łukasz Pomietło). Such a note in the documentation would certainly be advisable. Could a similar one be added to the `max`, `min` and `minmax` methods? There is one more issue. I think that someone who sees `(a.y <=> b.y).nonzero?` for the first time will not guess what is going on here without finding `nonzero?` in the documentation. Maybe it would be worth adding an alias for `nonzero?`? Maybe `ordinal`? ---------------------------------------- Feature #21157: Comparison operator <> https://bugs.ruby-lang.org/issues/21157#change-112191 * Author: lpogic (Łukasz Pomietło) * Status: Feedback ---------------------------------------- I propose introducing a comparison operator *<>* which would give the following results: ```ruby 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: ```ruby 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: ```ruby a = b = 1 a_not_equal_b if a <> b a_equal_b unless a <> b ``` -- https://bugs.ruby-lang.org/
participants (5)
-
Eregon (Benoit Daloze)
-
Hanmac (Hans Mackowiak)
-
lpogic
-
nobu (Nobuyoshi Nakada)
-
P3t3rU5 (Pedro Miranda)