Improved operator lookup semantics

Something else. As @xwu mentions, this is the payoff that never materialized due to structural concerns in the type system. I'm arguing (at the limit) for something like this:

protocol LessThanable {
  // This is not spelled "func <" and not injected into the global scope!!
  static func lessThan(a : Self, b : Self) -> Bool
}

// There can be only one, and it shall be (T,T)->Bool   (*)
func < <T : LessThanable>(a : T, b: T) -> Bool {
  return T.lessThan(a: a, b: b)
}

// not actually allowed :(  - you know what I mean.
extension BinaryInteger : LessThanable {
  static func lessThan(a : Self, b : Self) -> Bool {
    ...
  }
}

Similarly you do that with FP types, and all of the other concrete implementations of the types. The point is that the compiler does name lookup of < and finds exactly one match. This means that the exponential search of various possibilities has to consider exactly one operator instead of N when it sees "42 < x".

Now, we have a complication here: for comparisons (but not normal arithmetic) we went down the path of allowing mixed operands to comparisons (which was perhaps a bad idea in hindsight). This means you need a second mixed operator like:

func < <T, S>(a: T, b: S) -> Bool {
   ...
}

It is unfortunate that we have to support 2 implementations (meaning we get a disjunction in the constraint solver) but one disjunction with 2 possibilities should be FAR FAR Better than a disjunction with N possibilities - each of which need to be exponentially searched. Also, this issue doesn't affect + or * or other non comparison operations.

-Chris

2 Likes