patternswiftMinor
Optimal custom operator with generic type constraint for numerical type
Viewed 0 times
genericoptimaloperatorwithnumericaltypecustomforconstraint
Problem
I'm implementing (for an article) two custom infix operators:
After debugging some errors and looking for information I finally found a way to get my code working:
The output:
Do you thinks there could be a more optimal and readable approach? Could you give some advice or share an example?
¿%- to calculate percent of total
%?- to calculate the percent that represents a segment of total
After debugging some errors and looking for information I finally found a way to get my code working:
protocol NumericType {
static func *(lhs: Self, rhs: Self) -> Self
static func *(lhs: Self, rhs: Int) -> Self
static func /(lhs: Self, rhs: Self) -> Self
static func /(lhs: Self, rhs: Int) -> Self
} // NumericType
extension Double : NumericType {
internal static func *(lhs: Double, rhs: Int) -> Double {
return lhs * Double(rhs)
}
internal static func /(lhs: Double, rhs: Int) -> Double {
return lhs / Double(rhs)
}
} // extension Double : NumericType
extension Float : NumericType {
internal static func *(lhs: Float, rhs: Int) -> Float {
return lhs * Float(rhs)
}
internal static func /(lhs: Float, rhs: Int) -> Float {
return lhs / Float(rhs)
}
} // extension Float : NumericType
extension Int : NumericType { }
infix operator ¿%
func ¿% (percentage: T, ofThisTotalValue: T) -> T {
return (percentage * ofThisTotalValue) / 100
} // infix operator ¿%
infix operator %?
func %? (segment: T, ofThisTotalValue: T) -> T {
return (segment * 100) / ofThisTotalValue
} // infix operator %?
let percentage: Double = 8
let price: Double = 45
let save = percentage ¿% price
print("\(percentage) % of \(price) $ = \(save) $")
print("\(save) $ of \(price) $ = \(save %? price) %")The output:
8.0 % of 45.0 $ = 3.6 $
3.6 $ of 45.0 $ = 8.0 %Do you thinks there could be a more optimal and readable approach? Could you give some advice or share an example?
Solution
I imagine that you started out with something like this:
And received the error:
binary operator '*' cannot be applied to operands of type 'T' and 'Double'
You've solved this by creating a function with signature
The alternative approach is to to find a way to convert NumericType to a double so that in the end you're doing the multiplication on two doubles:
An implementation of this would look something like this:
However, please please please reconsider using custom operators like this.
I don't think that it's improving the readability or maintainability of your code, and unless you're using it every single day, I feel like it's something that will cause headaches in the future.
infix operator ¿%
func ¿% (percentage: T, ofTotal: Double) -> Double {
return percentage * ofTotal / 100.0
}And received the error:
binary operator '*' cannot be applied to operands of type 'T' and 'Double'
You've solved this by creating a function with signature
NumericType * Double -> Double... which works, but as you've found requires a bunch of boilerplate.The alternative approach is to to find a way to convert NumericType to a double so that in the end you're doing the multiplication on two doubles:
(NumericType -> Double) * Double - > DoubleAn implementation of this would look something like this:
protocol NumericType {
var doubleValue: Double { get }
}
infix operator ¿%
infix operator %?
func ¿% (percentage: T, ofTotal: Double) -> Double {
return percentage.doubleValue * ofTotal / 100.0
}
func %? (segment: T, ofTotal: Double) -> Double {
return segment.doubleValue * 100 / ofTotal
}
extension Double: NumericType {
var doubleValue: Double { return self }
}
extension Int: NumericType {
var doubleValue: Double { return Double(self) }
}However, please please please reconsider using custom operators like this.
I don't think that it's improving the readability or maintainability of your code, and unless you're using it every single day, I feel like it's something that will cause headaches in the future.
Code Snippets
infix operator ¿%
func ¿% <T: NumericType>(percentage: T, ofTotal: Double) -> Double {
return percentage * ofTotal / 100.0
}protocol NumericType {
var doubleValue: Double { get }
}
infix operator ¿%
infix operator %?
func ¿% <T: NumericType>(percentage: T, ofTotal: Double) -> Double {
return percentage.doubleValue * ofTotal / 100.0
}
func %? <T: NumericType>(segment: T, ofTotal: Double) -> Double {
return segment.doubleValue * 100 / ofTotal
}
extension Double: NumericType {
var doubleValue: Double { return self }
}
extension Int: NumericType {
var doubleValue: Double { return Double(self) }
}Context
StackExchange Code Review Q#150024, answer score: 2
Revisions (0)
No revisions yet.