> On May 18, 2016, at 3:14 PM, Nicola Salmoria <[email protected]> 
> wrote:
> 
> 
> 
> On Wed, May 18, 2016 at 10:03 PM, Matthew Johnson <[email protected] 
> <mailto:[email protected]>> wrote:
> 
>> On May 18, 2016, at 3:00 PM, Nicola Salmoria via swift-evolution 
>> <[email protected] <mailto:[email protected]>> wrote:
>> 
>> 
>> 
>> On Wed, May 18, 2016 at 8:03 PM, Tony Allevato <[email protected] 
>> <mailto:[email protected]>> wrote:
>> On Wed, May 18, 2016 at 10:02 AM Nicola Salmoria via swift-evolution 
>> <[email protected] <mailto:[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 
>> <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?

No, it’s not possible today so there is no existing code to reference.  
However, if you give people a choice some people will inevitably make a 
different choice than other people.

> 
> I expect the stdlib to illustrate what idiomatic Swift is expected to be, and 
> people to follow suit for the standard operators.

That is exactly what this proposal is attempting to do, and in a way that the 
language enforces the decision.  

> 
> 
> 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.

Are you specifically thinking of assignment operators?  If so, I wouldn’t have 
a problem if the proposal specified assignment operators as instance methods 
and all other operators as static methods.  As long as there is only one way to 
define a specific operator requirement I will be happy.

> 
> 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.

There is no difference in capability here so I’m not sure what you mean by 
having different “needs”.

>  
> 
>>  
>> (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] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to