- Proposal: SE-NNNN
- Author: Vanderlei Martinelli
- Status: Awaiting review
- Review manager: TBD
The proposal aims to allow operator implementation inside extension/struct/class instance scope.
Swift-evolution thread: link to the discussion thread for that proposal
When writing the protocol interface the operator is declarated inside the scope of that protocol, but its implementation has to be static and global. This, besides being inconsistent, might not the behaviour expected by programmers coming from other languages that have some kind of support for interface/protocol and operator implementation.
Example:
// MARK: - protocol
public protocol MyDoubleType {
public func someUsefulFunction()
public func *(lhs: Self, rhs: Self) -> Self
public postfix func ++(inout x: Self) -> Self
}
// MARK: - implementation
extension Double: MyDoubleType {
public func someUsefulFunction() {
// ...
}
// we cannot implement the operators here...
}
// ... but have to implement them here
public func *(lhs: Double, rhs: Double) -> Double {
return lhs.multipliedBy(rhs)
}
public postfix func ++(inout x: Double) -> Double {
let oldValue = x
x += 1.0
return oldValue
}
Also the current implementation does not leave much room for future expansion in the use of operators (such as conversion between values, for example).
Allow the operator implementation inside extension/struct/class scope turning these operator funcs into instance funcs.
After the change the above code can be written like the example below.
// MARK: - protocol
public protocol MyDoubleType {
public func someUsefulFunction()
public func *(rhs: Self) -> Self
public mutating postfix func ++() -> Self
}
// MARK: - implementation
extension Double: MyDoubleType {
public func someUsefulFunction() {
// ...
}
public func *(rhs: Double) -> Double {
return self.multipliedBy(rhs)
}
public mutating postfix func ++() -> Double {
let oldValue = self
self += 1.0
return oldValue
}
}
An operator does not have to be implemented only to conform to a protocol, however. It can be also be implemented in any other place where a common func is. This means that even the current form will also be supported.
Perhaps because of the internal implementation of Swift, operators have to have names to be handled. The suggestion is to adopt greaterThanOrEqualOperator
for a >=
operator, as example. The operator introduction would be:
infix operator >= {
associativity none
precedence 130
name greaterThanOrEqualOperator
}
So the code will be written like this...
struct MyStruct {
func >=(other: MyStruct) -> Bool {
return ...
}
}
... but translated internally to this:
struct MyStruct {
func greaterThanOrEqualOperator(other: MyStruct) -> Bool {
return ...
}
}
And then to _TCF...
using the current name mangling system.
Since after this change an operator can be implemented in any other place where a common func can be, the current implementation will continue to be supported without affecting the existing code base.
Leave things as they are. Even being inconsistent or not allowing new possibilities that instance operators will bring.
This is the way operators are implemented in C#, for example. The change would be only aesthetic. The functionality would remain the same as today.
As the types may differ from protocol/structure/class, this would allow state within the scope of operators that have nothing to do with that type. Not a good thing. In this case it might be better to keep things as they are.
Example:
// MARK: - protocol
public protocol MyDoubleType {
public func someUsefulFunction()
public static func *(lhs: Self, rhs: Self) -> Self
public static func /(lhs: Int64, rhs: Int64) -> Int64 // what?
public static postfix func ++(inout x: Self) -> Self
}
// MARK: - implementation
extension Double: MyDoubleType {
public func someUsefulFunction() {
// ...
}
public static func *(lhs: Double, rhs: Double) -> Double {
return lhs.multipliedBy(rhs)
}
// this should be implemented inside a Int64 type, not here...
public static func /(lhs: Int64, rhs: Int64) -> Int64 {
// ...
}
public static postfix func ++(inout x: Double) -> Double {
let oldValue = x
x += 1.0
return oldValue
}
}
Hello from devgrid