Reputation: 127
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
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).
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
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
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