Adrian
Adrian

Reputation: 127

Infinite Loop Issue with Static Operators in Swift Extensions (Learning Purposes)

I'm encountering a problem with using both + and * static functions in a Swift extension. I just want + to be * and * to be +. When I use just the + operator, it works fine, but when I include both operators, I run into an infinite loop.

Works fine

extension Int {
    static func + (left: Int, right: Int) -> Int {
        return (left * right)
    }
}

// 12
print(3 + 4)
// 12
print(3 * 4)

Now is going into an infinite loop

extension Int {
    static func + (left: Int, right: Int) -> Int {
        return (left * right)
    }
    
    static func * (left: Int, right: Int) -> Int {
        return (left + right)
    }
}

print(3 + 4)
print(3 * 4)

Any suggestions would be appreciated.


Cool trick for debugging use print(#function), see below in comments.

Upvotes: 1

Views: 121

Answers (3)

Adrian
Adrian

Reputation: 127

So here was the thing that I was looking for:

import Foundation

extension Int {    
    static func + (left: Int, right: Int) -> Int {
        return (left &* right)
    }
        
    static func * (left: Int, right: Int) -> Int {
        return (left &+ right)
    }
}


// 12
print(3 + 4)
// 7
print(3 * 4)

"In Swift, the &+, &-, and &* operators provide arithmetic operations that don't trap on overflow but instead wrap around using two's complement representation. This simulates how many lower-level languages (like C) handle arithmetic overflow and how hardware instructions for arithmetic operations work."


I have no clue whatever the above explanation means, if some1 can explain this in details that would be great. I know that &* is overflow-safe multiplication but what it does, and how it is used by swift I do not know. Thanks (just comment under this answer).

EDIT

Check this video Fast Conversion From Cpp Floating Point Numbers - Cassio Neri - C++Now 2024 good stuff in there. Maybe somehow this works like that, If some1 could elaborate on this thing that would be amazing.

Some additional info: Overflow Operators, and this also Table of 4-bit Binary System With the TWOs Complement Method

Upvotes: 0

Sweeper
Sweeper

Reputation: 273540

The two operators you declared in the extensions keep on calling each other. The easiest way to avoid this is to not use + or * in the bodies of those operators.

We want a way to call the built-in + and *, even in the presence of the extension. Luckily, + and * in Int are protocol witnesses to the + and * requirements in the Numeric protocol. We can call + and * through Numeric:

// * and + in these functions will not resolve to the ones you declared in the extension
func add<T: Numeric>(_ lhs: T, _ rhs: T) -> T {
    lhs + rhs
}
func multiply<T: Numeric>(_ lhs: T, _ rhs: T) -> T {
    lhs * rhs
}

// your custom + and * operators can be implemented with the above functions
extension Int {
    static func + (left: Int, right: Int) -> Int {
        return multiply(left, right)
    }
    
    static func * (left: Int, right: Int) -> Int {
        return add(left, right)
    }
}

Of course, the same approach will not work if you want to swap + and * for every Numeric type, but this trick does work for any type that is "more specific" than Numeric, like FloatingPoint, SignedNumeric etc.

Upvotes: 1

Adrian
Adrian

Reputation: 127

Please post an answer if you got a better one (looking to modify built-in + and built-in *).

infix operator ++
infix operator **

extension Int {
    static func ++ (left: Int, right: Int) -> Int {
        return (left * right)
    }
    
    static func ** (left: Int, right: Int) -> Int {
        return (left + right)
    }
}



// 12
print(3 ++ 4)
// 7
print(3 ** 4)

Extension inside a function is not allowed (Declaration is only valid at file scope) so swift does not allow the reassignment or shadowing of operators within local scopes, so if some1 came with a solution is much appreciated.

Upvotes: 0

Related Questions