nim-lang / RFCs

A repository for your Nim proposals.
135 stars 26 forks source link

General comparison operator (a bit like a spaceship operator) #546

Closed ASVIEST closed 5 months ago

ASVIEST commented 6 months ago

Abstract

Inspired by C++ 20 spaceship operator (<=>).

General comparison operator just generates different binary operator for any variant (not std::strong_ordering etc.) so it no a Three-way comparison (see https://en.wikipedia.org/wiki/Three-way_comparison).

this operator generates ==, !=, >, <, >=, <= operators, so it can remove some boilerplate

Motivation

No response

Description

It just generates different comparison variants. Maybe ∨ and ∧ symbols is not the most convenient way to indicate comparisons.

Code Examples

type MyType = object
  val: int

proc `∨`(a, b: MyType): bool =
  echo a.val ∧ b.val # ∧ is opposite operation(it's just a not a.val ∨ b.val)
  a.val ∨ b.val # for ∨ can be used also v

var t = MyType(val: 5)
var z = MyType(val: 7)
assert t != z
assert t < z
assert t <= z

discard t ∨ z # raises an Exception like general comparison operator can be used only in other general comparison operator

Backwards Compatibility

No response

konsumlamm commented 6 months ago

∨ and ∧ are very bad names for this, since they're used for "or" and "and" in math. I think if anything, such an operator should have a name like cmp or compare, rather than a confusing operator that people have to learn first.

Prior art:

metagn commented 6 months ago

Other prior art: https://nim-lang.org/docs/system.html#cmp%2CT%2CT

ASVIEST commented 6 months ago

In math it can be used not only as disjunction and coconjunction, but as any comparison operation and its opposite. Yes it's not perfect, but I haven't found a better design. cmp usually means exactly Three-way comparison, including in std.

proc `=cmp`(a, b: MyType): int =
  cmp(a.val, b.val)

This is a bit odd since our procedure is =cmp, but it uses cmp, not =cmp. If this operator is not =cmp but just cmp, then all types with cmp procedure will implement <, >, <=, >= and so on, it is a bit strange for some data types, for example for some arrays or strings, which will have their own cmp, there will need std:weak_ordering from C++ and so on to show that most of these boolean operators are unnecessary (except ==, !=). Also, as for me, cmp is a bit worse for reading code than just bool operators, which look like operators, where you can use and, or etc. BTW the v operator can also generate cmp proc for operands.

metagn commented 6 months ago

I just understood what you were actually suggesting (you only seemed to describe what it was not), I think you mean:

proc `∨`(a, b: MyType): bool =
  echo a.val ∧ b.val
  a.val ∨ b.val

should be sugar for:

proc `<`(a, b: MyType): bool =
  echo a.val > b.val
  a.val < b.val
proc `<=`(a, b: MyType): bool =
  echo a.val >= b.val
  a.val <= b.val

We already have templates and macros to do stuff like this.