I made a little "Angle" enum so that I could program with different interchangeable angular formats:
enum Angle {
case Radians(CGFloat)
case Degrees(CGFloat)
case Rotations(CGFloat)
}
I find that there's some redundant boilerplate code with this approach though. For example, I wanted to add a computed var that just returned the raw underlying associated float:
var raw:CGFloat {
switch self {
case let .Radians(value):
return value
case let .Degrees(value):
return value
case let .Rotations(value):
return value
}
}
I tried to change that to read:
case .Radians(let value), .Degrees(let value):
return value
I hoped it would be clever enough to realize it was only ever going to resolve one match, so the conflict was ignorable. But no such device. Compiler says it can't resolve the conflict between the two let value
statements.
So is there a bit of idiomatic cleverness I haven't discovered with Swift enum's yet that would make it so I don't have to repeat myself so much there?
Another similar example, was when I implemented the *
function:
func * (lhs:Angle, rhs:CGFloat) -> Angle {
switch lhs {
case .Radians:
return .Radians(lhs.raw * rhs)
case .Degrees:
return .Degrees(lhs.raw * rhs)
case .Rotations:
return .Rotations(lhs.raw * rhs)
}
}
It seems like there should be a simpler way to express that: "Make the same enum type with my associated value times the scalar argument".
(I'm not sure I've got a good title on this question, feel free to improve/suggest better)
That's an interesting case: An enum somehow isn't the right data type, because the value isn't either in radians or in degrees, both are just angles and not really different things. Also typealias Radians = Double
wouldn't work because there's no unit safety.
Maybe you can use something like this though:
import Darwin
struct Angle {
enum Unit {
case Radians
case Degrees
case Rotations
var radiansFactor : Double {
switch self {
case Radians: return 1
case Degrees: return 180.0 / M_PI
case Rotations: return 1 / 2 / M_PI
}
}
}
var unit : Unit {
didSet {
value /= oldValue.radiansFactor
value *= unit.radiansFactor
}
}
var value : Double
}
func * (var lhs: Angle, rhs: Double) -> Angle {
lhs.value *= rhs
return lhs
}
var angle = Angle(unit: .Degrees, value: 180)
angle.value // 180.0
angle.unit = .Radians
angle.value // 3.141592...
angle.unit = .Rotations
angle.value // 0.5
Oh and as for the answer to your original question: No you cannot.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With