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

Nicola Salmoria nicola.salmoria at gmail.com
Wed May 18 12:02:35 CDT 2016


> * What is your evaluation of the proposal?

I'm generally in strong support, having long been a proponent of removing
operators from protocols (the first occurrence was in this thread:
http://article.gmane.org/gmane.comp.lang.swift.evolution/7935)

I have several comments about the details of the proposal, however.

1) At the beginning, in the "Proposed solution" section, the proposal says
"This document does not propose that the current way of defining operators
be removed or changed at this time. Rather, we describe an addition that
specifically provides improvements for protocol operator requirements."

Later, however, there is a "Deprecation of non-static protocol operators"
section which suggest to do exactly that, and this is reiterated in the
"Impact on existing code" section.

Since I think that the deprecation of global operator overloads is the
crucial point of the proposal, I assume that the former is an oversight.

2) The method signatures in the examples are not up to date with the current
Swift 3 syntax. For example:

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

should be:

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

3) As has already been noted by many others, the suggested syntax for
prefix/postfix operators is overcomplicated. The proposal is:

// These are deprecated, of course, but used here just to serve as an
// example.
static prefix func ++(_ value: inout Self) -> Self
static postfix func ++(_ value: inout Self) -> Self

We don't need that. Since the 'operators' declared inside protocols are
effectively just normal methods (apart from their names), we just need to
name the parameters accordingly:

static func ++(prefix value: inout Self) -> Self
static func ++(postfix value: inout Self) -> Self

4) I don't agree with the request to limit to static methods for the
operator implementations.
I support this for symmetrical binary operators like +, but there are other
operators like += that seem to work better with members. That is, the
proposed declaration:

static func +=(_ lhs: inout Self, _ rhs: Self)

is more similar to the global += operator definition, but is less clear than:

mutating func +=(_ rhs: Self)

this is apparent also at the call site. With the proposed syntax, one would
need to do:

func +=<T: Foo>(_ lhs: inout T, _ rhs: T) {
    T.+=(lhs, rhs)
}

while with a member function this would read more naturally as:

func +=<T: Foo>(_ lhs: inout T, _ rhs: T) {
    lhs.+=(rhs)
}

5) the proposal mentions the open question of ambiguities between the dot
syntax to access methods and operators whose name starts with a dot.
This seems to be a real issue: I don't think

return T....(minimum, maximum)

looks any good, even if the compiler was able to parse it.

However, this just means that the methods used to implement operators with
problematic names would need to use different names. Arguably, the only
cases where one would really want to use methods with operator names is for
arithmetical operators. Custom operators like ... are better expressed as
methods with more significant names.

6) It seems somewhat arbitrary to restrict method names to match an
operator, nor to put requirements on the function signature. I'd say there
are two cases, either the compiler can handle a method name that uses
special characters, or it can't. If it can't, matching an operator name
won't help. If it can, why put limits? There could be other creative uses of
such names, which we would be ruling out for no particular reason. This is
something that seems better left to the author of the protocol.

7) Automatic generation of trampoline functions is out of scope so I'm not
going to talk much about it, I only want to mention that it would make sense
to consider making such a feature as general as possible, instead of
focusing exclusively on operators.

For example, think of the common mathematical functions like sin, cos, etc.
It could make sense to give them the same treatment as operators, declaring
them as part of the FloatingPoint protocol but preserving the global
functions too.
It might even make sense to be able to create trampolines not only from
global space to a type, but also from one type to another type, or even for
all methods of a type (e.g. when boxing a value inside another type).

> * Is the problem being addressed significant enough to warrant a change to
Swift?

Absolutely. The handling of operators in protocols has been one of the worst
pain points in my use of Swift.

> * Does this proposal fit well with the feel and direction of Swift?

Yes; it significantly increases clarity and consistency.

> * If you have used other languages or libraries with a similar feature,
how do you feel that this proposal compares to those?

I only have experience with C++ operator overloading, which is much less
advanced.

> * How much effort did you put into your review? A glance, a quick reading,
or an in-depth study?

An in-depth study of the proposal, and I read all the relevant threads on
the mailing list.

--
Nicola




More information about the swift-evolution mailing list