[swift-evolution] [Proposal] Instance Operators

Andrew Bennett cacoyi at gmail.com
Fri Mar 4 06:54:24 CST 2016


I'm +1 on Nicola's suggestions.

Basically, remove operators from protocols, simplifying the language. This
doesn't prevent operators from using protocols (through generics).

Operators with protocols can still be defined as Nicola suggested, through
a regular protocol method and a generic. Symmetrical operators can use a
static method on the protocol if that's desirable. Swift has all the
functionality for this already.

It also doesn't have the downside of preventing operators from working on
things like types, tuples, etc.


On Mon, Feb 29, 2016 at 5:24 PM, Thorsten Seitz via swift-evolution <
swift-evolution at swift.org> wrote:

>
> > Am 26.02.2016 um 17:55 schrieb Sean Heber via swift-evolution <
> swift-evolution at swift.org>:
> >
> > I agree with all of this. I’m not sure operators really belong *inside*
> of the type. IMO, attempting to include them within the type is only
> desirable because of the way they are declared inside of the protocol. I
> think the asymmetry should be addressed on that side instead (if at all).
>
> Good point! Maybe we should think about turning operators into
> multi-methods which are dynamically dispatched on all arguments like Dylan
> had. Or at least just move their declaration out of protocols.
>
> -Thorsten
>
> >
> > l8r
> > Sean
> >
> >
> >
> >> On Feb 26, 2016, at 10:43 AM, plx via swift-evolution <
> swift-evolution at swift.org> wrote:
> >>
> >> After careful consideration, I am not sure this sort of thing is
> actually a change that would *actually* be an obvious improvement.
> >>
> >> # First Concern: Code-Organization/Ownership Issues
> >>
> >> Although it is easy to see how to handle operators that have
> *homogenous* types — e.g. anything like `func +(lhs: T, rhs: T) -> T` —
> it’s really unclear how a proposal like this *should* work for operators
> that have *heterogeneous* types — e.g. anything like `func *(lhs: T, rhs:
> U) -> U ` (etc.).
> >>
> >> Since we’re talking about operators, this isn’t really a hypothetical
> concern, either:
> >>
> >> ## Example: Vector/Matrix Operations
> >>
> >> func *(lhs: Matrix4x4, rhs: Vector4) -> Vector4
> >> func *(lhs: Vector4, rhs: Matrix4x4) -> Vector4
> >>
> >> Both operations are reasonable to define, but defining the operator as
> instance methods seems to leave you in a rather awkward spot:
> >>
> >> - perhaps one is implemented by `Matrix4x4` and the other by `Vector4`
> (really odd code organization imho…)
> >> - perhaps both are implemented by, say, `Matrix4x4`, but one of them is
> using nonstandard syntax (defeating the point of custom operators, imho)
> >> - perhaps the proposal lets an operator-function declaration indicate
> *which* argument is `self` (new syntax/new semantics)
> >>
> >> …whereas the “operators are static functions” approach makes it
> reasonable to have both versions defined at the same scope (and e.g. "near
> each other”).
> >>
> >> I know the specific proposal here wouldn’t eliminate the ability to
> define the operators as currently, but it’d be a shame to be unable to
> include things like the above method in protocols.
> >>
> >> ## Example: Scalar/Vector Operations
> >>
> >> Similarly, at a more-basic level, you might *want* this:
> >>
> >> protocol VectorType : Equatable {
> >>  typealias Component : NumericType // if it existed
> >>
> >>  // to match convention, scalars go *in front* of vectors
> >>  operator *(lhs: Int, rhs: Self) -> Self
> >>  operator *(lhs: Self.Component, rhs: Self) -> Self
> >>
> >>  // but why should we not be flexible on this point?
> >>  operator *(lhs: Self, rhs: Int) -> Self
> >>  operator *(lhs: Self, rhs: Self.Component) -> Self
> >> }
> >>
> >> …and are we going to make `struct Vector4`’s conformance to
> `VectorType` contingent on the presence of extension methods on `Int`
> (etc.)?
> >>
> >> That just seems really unintuitive and counterproductive.
> >>
> >> # Second Concern: Dynamic Operator Dispatch Not Really Necessary
> >>
> >> What I mean is, in the use cases that come to mind for dynamic
> operator-dispatch. making operators dynamically-dispatched wouldnt’
> actually provide any benefit over what you can achieve today with protocols.
> >>
> >> EG, for `==`, consider a protocol and operators like below:
> >>
> >> protocol DynamicEquatable : class {
> >>  func isEqual(other: Self) -> Bool
> >> }
> >>
> >> func ==<T:DynamicEquatable>(lhs: T, rhs: T) -> Bool {
> >>  return (lhs === rhs) || lhs.isEqual(rhs)
> >> }
> >>
> >> func !=<T:DynamicEquatable>(lhs: T, rhs: T) -> Bool {
> >>  return (lhs !== rhs) && !lhs.isEqual(rhs)
> >> }
> >>
> >> …which as far as I can tell gets you back to the same place you’d be if
> you had a dynamically-dispatched `==` (both in terms of *what it would do*
> and also *what issues it would still have*).
> >>
> >> Is there some (beneficial?) aspect of making `==`
> dynamically-dispatched that isn’t also present in the above design?
> >>
> >> Are there operators for which there would be a material difference
> between the operator being dynamically-dispatched and the operator being
> defined over a protocol that has a dynamically-dispatched method providing
> the implementation?
> >>
> >> # Remark
> >>
> >> For `==` in particular, you could *maybe* improve the above slightly if
> Swift had a way to write a where clause like `U:>T` — meaning “U is a
> subclass of T, but not T itself” — as then you could add variants like:
> >>
> >> func ==<T:DynamicEquatable,U:DynamicEquatable where T:>U>(lhs: T, rhs:
> U) -> Bool {
> >>  return (lhs === rhs) || lhs.isEqual(rhs)
> >> }
> >>
> >> func ==<T:DynamicEquatable,U:DynamicEquatable where U:>T>(lhs: T, rhs:
> U) -> Bool {
> >>  return (lhs === rhs) || rhs.isEqual(lhs)
> >> }
> >>
> >> …which would hopefully make a direct call into the more-derived type’s
> implementation of `isEqual`, which would be more-likely to contain a fast
> path, but even so it’s not obvious that there’s all that much of an actual
> win to be had here, in practice.
> _______________________________________________
> 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/20160304/e8f21c0f/attachment-0001.html>


More information about the swift-evolution mailing list