On Wed, May 18, 2016 at 10:03 PM, Matthew Johnson <[email protected]> wrote:
> > On May 18, 2016, at 3:00 PM, Nicola Salmoria via swift-evolution < > [email protected]> wrote: > > > > On Wed, May 18, 2016 at 8:03 PM, Tony Allevato <[email protected]> > wrote: > >> On Wed, May 18, 2016 at 10:02 AM Nicola Salmoria via swift-evolution < >> [email protected]> wrote: >> >>> > * 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. >>> >> >> I could probably do a better job of clarifying the wording here. The >> proposal does *not* deprecate *all* global operator overloads. Global >> operators can still be implemented as they have been in Swift. So if you >> have a concrete type like `struct Matrix`, you can still define at the >> global level `func +(lhs: Matrix, rhs: Matrix) -> Matrix`. >> >> What's being deprecated is the current syntax used to define operator >> requirements inside protocols (by making the functions static) and the >> manner by which subtypes conform (ditto, through static methods instead of >> global functions). >> > > OK, I guess the unclear part is when you talk about "an addition that > specifically provides improvements for protocol operator requirements." > This is not just an addition; it's intended to completely replace the > protocol operator syntax. > >> >> >>> 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 >>> } >>> >> >> Unless I'm mistaken, from looking at the Swift 3 branch of stdlib, the >> syntax changes don't appear to apply to operator functions. Since they are >> a special case that don't have argument labels, it wouldn't make sense to >> require them (or rather, the placeholders) here. >> > > I don't agree with this. > > Operators are called like this: > > x = y + z > > Of course it doesn't make sense to have parameter labels there. > > But the ones inside the protocol are not operators. They are methods, and > are called like methods. They happen to have funny names, but they are > still methods, and are called like this: > > x = T.+(y, z) > > In this case not only it makes sense for the parameters to have labels, > but making them behave differently from normal methods would be > inconsistent, and a step backwards from all the progress that has been made > in Swift 3 on that front. > > >> >> >>> 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) >>> } >>> >> >> I considered this, but eventually settled on "everything is static" for >> consistency. As you mention, there's a stronger argument to be made for >> assignment operators to have "left hand side is the receiver" semantics >> than there are for standard infix operators, but from a consistency point >> of view (and ease of learning), I think having everything static and the >> signatures of the static operators matching those of the global operators >> is preferable. >> > > I think this would better be left as a choice to the author of the > protocol. There doesn't seem to be any technical reason to place this > restriction. > > > The problem with this is that people will make different choices. This > may result in boilerplate where a type has to provide both static *and* > instance methods to conform to different protocols. Better to avoid that > possibility. > Do you have a specific example in mind? I expect the stdlib to illustrate what idiomatic Swift is expected to be, and people to follow suit for the standard operators. > What benefit do you perceive in allowing operator instance methods? > The fact that operators like += are more naturally implemented as an instance method than as a static method is already a clear benefit to me. But in general, there aren't only the standard operators; people will define custom operators and will have different needs depending on their semantics. If there isn't a technical limitation, I don't see a reason to add arbitrary restrictions. > > > >> (Which is also why, as I mentioned in a previous reply, I would be open >> to dropping the prefix/postfix keyword and making it an argument label >> instead, in both contexts.) >> >> >>> >>> 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. >>> >> >> If there is a strong case where an operator is better implemented as a >> global operator and a named method, this proposal still allows that, since >> it's not deprecating all global operator definitions. A protocol could >> certainly have a requirement that is a named method, and provide a global >> generic operator that calls it. >> >> >>> >>> 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. >>> >> >> IMO, to reduce potential confusion, I would argue that a function whose >> name is the same as a defined operator should conform to the requirements >> (such as argument count) of that operator. It's certainly worth discussion, >> though! With that being said, it may be easier on users to "rule something >> out" now and open it up later if need be, rather than to leave it open for >> people to use and decide it needs to be closed later. >> > > This doesn't seem different to me from having multiple functions with the > same name and different signature, which Swift allows without problems. > Again, I think this is a choice that the author of the protocol should > make, and there doesn't seem to be any technical reason to require > otherwise. > > >> >> >>> 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 >>> >>> >>> _______________________________________________ >>> swift-evolution mailing list >>> [email protected] >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> >> > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution > > >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
