[Proposal] Instance Operators


(Thorsten Seitz) #1

Looks good to me, although I’m torn on the “operator” keyword. While I like it because it distinguishes operators from methods, so that there is no confusion about a missing implicit “self” within an operator definition, I am not happy about losing “operator” as a method or variable name.

-Thorsten

Hello.

The proposal can be also read at https://gist.github.com/vmartinelli/67d6ad234c7a4e14f8d5

Original thread: https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160125/008508.html

Opinions, comments and corrections (including on English grammar) are all welcome. :slight_smile:

-Van


Instance Operators

Introduction

The proposal aims to move operator implementation from the global and static scope into extension/struct/class instance scope.

Swift-evolution thread: link to the discussion thread for that proposal

Motivation

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 {
> x += 1.0
>     return x
> }

Also the current implementation does not leave much room for future expansion in the use of operators (such as conversion between values, for example).

Proposed solution

Move the operator implementation into the extension/struct/class scope and turn operator funcs into instance funcs, using the operator keyword.

Detailed design

Protocol conformance

After the change the above code can be written like the example bellow.

> // MARK: - protocol
> 
> public protocol MyDoubleType {
> public func someUsefulFunction
>     ()
> public operator *(rhs: Self) -> Self
>     public mutating postfix operator ++() -> Self
> }
> // MARK: - implementation
> 
> extension Double
>     : MyDoubleType {
> public func someUsefulFunction        () {
> // ...
>     }
> public operator *(rhs: Double) -> Double {
> return self.    multipliedBy(rhs)
> }
> public mutating postfix operator ++() -> Double {
> self += 1.0
>        return self
>     }
> }

Operator funcs everywhere

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 can be supported.

Operator internal names

Perhaps because of the internal implementation of Swift, operators have to have names to be handled. The suggestion is to adopt __operator__GreaterThanOrEqual for a >= operator, as example. The operator introduction would be:

> infix operator >= {
> associativity none
>     precedence 130
>     name "GreaterThanOrEqual"
> }

So the code will be written like this…

> struct MyStruct {
> operator >=(other: MyStruct) -> Bool {
> return ...
>     }
> }

… but translated internally to this:

> struct MyStruct {
> func __operator__GreaterThanOrEqual(other: MyStruct) -> Bool {
> return ...
>     }
> }

Impact on existing code

Since after this change an operator can be implemented in any other place where a common func can be, the current implementation may continue to exist, but marked as deprecated with a compiler/analyser warning.

Also the func keyword would be deprecated for operators as well, using the operator to declare/implement an operator func.

Alternatives considered

Status quo

Leave things as they are. Even being inconsistent or not allowing new possibilities that instance operators will bring.

Static implementation inside extension/struct/class scope

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 operator *(lhs: Self, rhs: Self) -> Self
>     public static operator /(lhs: Int64, rhs: Int64) -> Int64 // what?
>     public static postfix operator ++(inout x: Self) -> Self
> }
> // MARK: - implementation
> 
> extension Double
>     : MyDoubleType {
> public func someUsefulFunction        () {
> // ...
>     }
> public static operator *(lhs: Double, rhs: Double) -> Double {
> return lhs.    multipliedBy(rhs)
> }
> // this should be implemented inside a Int64 type, not here...
>     public static operator /(lhs: Int64, rhs: Int64) -> Int64 {
> // ...
>     }
> public static postfix operator ++(inout x: Double) -> Double {
> x += 1.0
>         return x
> }
> }
> 
···

Am 25. Februar 2016 um 20:59 schrieb Vanderlei Martinelli via swift-evolution swift-evolution@swift.org:


swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Pierre Monod-Broca) #2

For me it's
* -1 to have infix symmetrical operators (==, !=) be instance methods
* -0.5 for the operator keyword
* +1 to move the operators implementation inside class/struct/extension scope

In my experience == is a good example of operators better implemented as static funcs.

···

Le 26 févr. 2016 à 11:48, Thorsten Seitz via swift-evolution <swift-evolution@swift.org> a écrit :

Looks good to me, although I'm torn on the "operator" keyword. While I like it because it distinguishes operators from methods, so that there is no confusion about a missing implicit "self" within an operator definition, I am not happy about losing "operator" as a method or variable name.

-Thorsten

Am 25. Februar 2016 um 20:59 schrieb Vanderlei Martinelli via swift-evolution <swift-evolution@swift.org>:

Hello.

The proposal can be also read at https://gist.github.com/vmartinelli/67d6ad234c7a4e14f8d5

Original thread: https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160125/008508.html

Opinions, comments and corrections (including on English grammar) are all welcome. :slight_smile:

-Van

---------

Instance Operators

Proposal: SE-NNNN <https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-instance-operators.md>
Author: Vanderlei Martinelli <https://github.com/vmartinelli>
Status: Awaiting review
Review manager: TBD
Introduction

The proposal aims to move operator implementation from the global and static scope into extension/struct/class instance scope.

Swift-evolution thread: link to the discussion thread for that proposal <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160125/008508.html>
Motivation

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 {
    x += 1.0
    return x
}
Also the current implementation does not leave much room for future expansion in the use of operators (such as conversion between values, for example).

Proposed solution

Move the operator implementation into the extension/struct/class scope and turn operator funcs into instance funcs, using the operator keyword.

Detailed design

Protocol conformance

After the change the above code can be written like the example bellow.

// MARK: - protocol

public protocol MyDoubleType {
    public func someUsefulFunction()

    public operator *(rhs: Self) -> Self
    public mutating postfix operator ++() -> Self
}

// MARK: - implementation

extension Double: MyDoubleType {

    public func someUsefulFunction() {
        // ...
    }

    public operator *(rhs: Double) -> Double {
        return self.multipliedBy(rhs)
    }

    public mutating postfix operator ++() -> Double {
       self += 1.0
       return self
    }

}
Operator funcs everywhere

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 can be supported.

Operator internal names

Perhaps because of the internal implementation of Swift, operators have to have names to be handled. The suggestion is to adopt __operator__GreaterThanOrEqual for a >= operator, as example. The operator introduction would be:

infix operator >= {
    associativity none
    precedence 130
    name "GreaterThanOrEqual"
}
So the code will be written like this...

struct MyStruct {
    operator >=(other: MyStruct) -> Bool {
        return ...
    }
}
... but translated internally to this:

struct MyStruct {
    func __operator__GreaterThanOrEqual(other: MyStruct) -> Bool {
        return ...
    }
}
Impact on existing code

Since after this change an operator can be implemented in any other place where a common func can be, the current implementation may continue to exist, but marked as deprecated with a compiler/analyser warning.

Also the func keyword would be deprecated for operators as well, using the operator to declare/implement an operator func.

Alternatives considered

Status quo

Leave things as they are. Even being inconsistent or not allowing new possibilities that instance operators will bring.

Static implementation inside extension/struct/class scope

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 operator *(lhs: Self, rhs: Self) -> Self
    public static operator /(lhs: Int64, rhs: Int64) -> Int64 // what?
    public static postfix operator ++(inout x: Self) -> Self
}

// MARK: - implementation

extension Double: MyDoubleType {

    public func someUsefulFunction() {
        // ...
    }

    public static operator *(lhs: Double, rhs: Double) -> Double {
        return lhs.multipliedBy(rhs)
    }

    // this should be implemented inside a Int64 type, not here...
    public static operator /(lhs: Int64, rhs: Int64) -> Int64 {
        // ...
    }

    public static postfix operator ++(inout x: Double) -> Double {
        x += 1.0
        return x
    }

}

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Thorsten Seitz) #3

Oops, seems I read the proposal too fast.

I'm totally against symmetric implementing infix operators as instance methods!

I misread the proposal to just being able to group the definitions within a class or struct body. That's why I commented on the operator keyword as I did...

So, -1 for the proposal.

-Thorsten

···

Am 26.02.2016 um 14:40 schrieb Pierre Monod-Broca <pierre@monod-broca.fr>:

For me it's
* -1 to have infix symmetrical operators (==, !=) be instance methods
* -0.5 for the operator keyword
* +1 to move the operators implementation inside class/struct/extension scope

In my experience == is a good example of operators better implemented as static funcs.

Le 26 févr. 2016 à 11:48, Thorsten Seitz via swift-evolution <swift-evolution@swift.org> a écrit :

Looks good to me, although I'm torn on the "operator" keyword. While I like it because it distinguishes operators from methods, so that there is no confusion about a missing implicit "self" within an operator definition, I am not happy about losing "operator" as a method or variable name.

-Thorsten

Am 25. Februar 2016 um 20:59 schrieb Vanderlei Martinelli via swift-evolution <swift-evolution@swift.org>:

Hello.

The proposal can be also read at https://gist.github.com/vmartinelli/67d6ad234c7a4e14f8d5

Original thread: https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160125/008508.html

Opinions, comments and corrections (including on English grammar) are all welcome. :slight_smile:

-Van

---------

Instance Operators
Proposal: SE-NNNN
Author: Vanderlei Martinelli
Status: Awaiting review
Review manager: TBD
Introduction

The proposal aims to move operator implementation from the global and static scope into extension/struct/class instance scope.

Swift-evolution thread: link to the discussion thread for that proposal

Motivation

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 {
    x += 1.0
    return x
}
Also the current implementation does not leave much room for future expansion in the use of operators (such as conversion between values, for example).

Proposed solution

Move the operator implementation into the extension/struct/class scope and turn operator funcs into instance funcs, using the operator keyword.

Detailed design

Protocol conformance

After the change the above code can be written like the example bellow.

// MARK: - protocol

public protocol MyDoubleType {
    public func someUsefulFunction()

    public operator *(rhs: Self) -> Self
    public mutating postfix operator ++() -> Self
}

// MARK: - implementation

extension Double: MyDoubleType {

    public func someUsefulFunction() {
        // ...
    }

    public operator *(rhs: Double) -> Double {
        return self.multipliedBy(rhs)
    }

    public mutating postfix operator ++() -> Double {
       self += 1.0
       return self
    }

}
Operator funcs everywhere

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 can be supported.

Operator internal names

Perhaps because of the internal implementation of Swift, operators have to have names to be handled. The suggestion is to adopt __operator__GreaterThanOrEqual for a >= operator, as example. The operator introduction would be:

infix operator >= {
    associativity none
    precedence 130
    name "GreaterThanOrEqual"
}
So the code will be written like this...

struct MyStruct {
    operator >=(other: MyStruct) -> Bool {
        return ...
    }
}
... but translated internally to this:

struct MyStruct {
    func __operator__GreaterThanOrEqual(other: MyStruct) -> Bool {
        return ...
    }
}
Impact on existing code

Since after this change an operator can be implemented in any other place where a common func can be, the current implementation may continue to exist, but marked as deprecated with a compiler/analyser warning.

Also the func keyword would be deprecated for operators as well, using the operator to declare/implement an operator func.

Alternatives considered

Status quo

Leave things as they are. Even being inconsistent or not allowing new possibilities that instance operators will bring.

Static implementation inside extension/struct/class scope

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 operator *(lhs: Self, rhs: Self) -> Self
    public static operator /(lhs: Int64, rhs: Int64) -> Int64 // what?
    public static postfix operator ++(inout x: Self) -> Self
}

// MARK: - implementation

extension Double: MyDoubleType {

    public func someUsefulFunction() {
        // ...
    }

    public static operator *(lhs: Double, rhs: Double) -> Double {
        return lhs.multipliedBy(rhs)
    }

    // this should be implemented inside a Int64 type, not here...
    public static operator /(lhs: Int64, rhs: Int64) -> Int64 {
        // ...
    }

    public static postfix operator ++(inout x: Double) -> Double {
        x += 1.0
        return x
    }

}

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution