# [swift-users] Restricting associated values

Howard Lovatt howard.lovatt at gmail.com
Mon Jun 19 00:33:00 CDT 2017

```To me Angle is a unit with two common representations: radians and degrees.
It's not an enum because it doesn't have two values, it has one value that
you can view in two ways.

Therefore I would make an Angle struct, something like:

//: Angle struct instead of angle enum

import Foundation

struct Angle  {

static let d2R = Double.pi / 180

static let r2D = 180 / Double.pi

private var degs: Double

var degrees: Double {

return degs

}

var radians: Double {

return degs * Angle.d2R

}

init(degrees: Double = 0) {

degs = degrees.truncatingRemainder(dividingBy: 180)

}

self.init(degrees: radians * Angle.r2D)

}

}

extension Angle: Hashable {

var hashValue: Int {

return degs.hashValue

}

static func ==(lhs: Angle, rhs: Angle) -> Bool {

return lhs.degs == rhs.degs

}

}

extension Angle/*: FloatingPoint*/ {

static func +(lhs: Angle, rhs: Angle) -> Angle {

return Angle(degrees: lhs.degs + rhs.degs)

}

static func +=(lhs: inout Angle, rhs: Angle) {

lhs.degs += rhs.degs

lhs.degs = lhs.degs.truncatingRemainder(dividingBy: 180)

}

// Rest of FloatingPoint ...

}

// Trig

extension Angle {

var sin: Double {

return Foundation.sin(radians) // Need to qualify name to stop name
clash

}

// Other trig

}

let a = Angle(degrees: 90) // 90

a.radians // pi / 2

a.sin // 1

let b = Angle(radians: 3) // Almost pi

b.degrees // 171.9

let c = a + b // Wraps over 180 degrees

c.degrees // 81.9

c == b // false

c.hashValue // 463...

let d = Angle(degrees: -90) // -90

d.radians // -pi / 2

var e = Angle(radians: -3) // Almost -pi

e.degrees // -171.9

e += d // Wraps over -180 degrees

e.degrees // -81.9

-- Howard.

On 19 June 2017 at 13:32, David Sweeris via swift-users <
swift-users at swift.org> wrote:

>
> On Jun 18, 2017, at 19:30, Nevin Brackett-Rozinsky via swift-users <
> swift-users at swift.org> wrote:
>
> Is there a way to restrict the associated values of an enum? For example,
> suppose I have this type:
>
> enum Angle {
>     case degrees(Double)
> }
>
> I want to ensure that the radians values is always in [0, 2π) and the
> degrees values is always in [0, 360). Ideally I would like to write an
> initializer which is called when the user writes eg. “let x: Angle =
> .degrees(-45)” and contains the logic to wrap the provided value into the
> allowed range (in this case by adding a multiple of 360).
>
> I don’t see a way to do it. Is this possible?
>
> The closest I’ve found is to create auxiliary types such as
>
> struct Degree { … }
> struct Radian { … }
>
> and give them appropriate initializers, then use them for the associated
> values. However that is undesirable because it adds an extra level of depth
> to get at the actual numeric values.
>
> Is there a better way?
>
>
> Not off the top of my head, at least not without changing the syntax.
>
> You could add two inits, with different argument labels, and not directly
> set the case: “let x = Angle(degrees: -45)”
>
> You could add "public var radians: Double { get {...} set {...} }" (and
> again for "degrees") to `Angle`. The getter would need to switch on self
> to figure out if you need to convert between the two (like if someone said
> ".radians(2).degrees"): “var x = Angle.radians(0); x.degrees = -45"
>
> Alternately, you could add "subscript() -> Double" and switch on self in
> both the setter and the getter to figure out if you should be wrapping
> at 2π or 360 and to do any conversions: “var x: Angle = .radians(0); x[] =
> -45"
>
> Hope that helps
> - Dave Sweeris
>
> _______________________________________________
> swift-users mailing list
> swift-users at swift.org
> https://lists.swift.org/mailman/listinfo/swift-users
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20170619/d2ba98fa/attachment.html>
```