On Wed, May 18, 2016 at 10:27 PM, Tony Allevato <[email protected]> wrote:
> On Wed, May 18, 2016 at 1:00 PM Nicola Salmoria <[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. >> > > What I'm saying is, if you look at the Swift 3 branch of stdlib, global > operator functions still do not have argument labels. Picking one at > random: > https://github.com/apple/swift/blob/swift-3.0-branch/stdlib/public/core/String.swift#L329 > > If you're arguing that those functions should be forced to include `_` > placeholders, that's fine, but it's not accurate to say that the way > they're written in this proposal is a step backwards from all the progress > made in Swift 3. It is *consistent* with the way global operator functions > are currently declared in Swift 3. > > If it changes there, then it should change here as well. But they should > be the same, and making that change for global operator functions is not > part of the scope of this proposal. > I'm not talking about the global operator functions; I'm talking about the methods inside the protocol, which are methods and are called like methods; they are not operators. > > > >> >> >>> >>> >>>> 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. >> > >> >>> (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
