[swift-evolution] [swift-evolution-announce] [Review #2] SE-0091: Improving operator requirements in protocols

Tony Allevato allevato at google.com
Thu Jul 7 13:49:35 CDT 2016


On Thu, Jul 7, 2016 at 11:37 AM Daniel Resnick via swift-evolution <
swift-evolution at swift.org> wrote:

> What is your evaluation of the proposal?
>>
> +1
>
>
>> Is the problem being addressed significant enough to warrant a change to
>> Swift?
>>
> Yes, the current situation of defining a protocol required operator
> function globally is potentially confusing and feels inconsistent.
>
>
>> Does this proposal fit well with the feel and direction of Swift?
>>
> Yup.
>
> How much effort did you put into your review? A glance, a quick reading,
>> or an in-depth study?
>
> A reading.
>
> One thing that's not completely clear to me: if you implement the operator
> function as a class method and override it in a subclass, in what situation
> would the overridden version be called?
>

(Using a binary operator as an example) Since the signature of the operator
is (Self, Self), you would have a situation like the following:

protocol Equatable {
  static func ==(lhs: Self, rhs: Self) -> Bool
}

class A: Equatable {
  class func ==(lhs: A, rhs: A) -> Bool { ... }
}

class B: A {
  class func ==(lhs: B, rhs: B) -> Bool { ... }
}

There is actually no overriding happening here, because the argument types
are different.

So,

    let a = A()
    let b = B()
    let b_as_a: A = B()

    b == B()  // should call B.==
    a == B()  // should call A.==, because the only match is by upcasting B
to A
    b == b_as_a  // should call A.==, because the dispatch is done
statically

The latter of those may seem surprising, but it's not a regression—the
current global operators would do the same (and Swift would need
multiple-dispatch to solve this).

That being said, it's likely that you would want to be able to call A's ==
implementation as part of B's. And it just occurs to me that we don't need
to support "super" to do this—the solution is rather elegant:

    class func ==(lhs: B, rhs: B) -> Bool {
      guard lhs as A == rhs as A else {
        return false
      }
      return lhs.someOtherProperty == rhs.someOtherProperty
    }

By explicitly casting the arguments to their superclass, the operator type
dispatch (which is based on the static types of the arguments) will call
the correct implementation.



> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160707/cd49a43b/attachment.html>


More information about the swift-evolution mailing list