<div dir="ltr">To me Angle is a unit with two common representations: radians and degrees. It&#39;s not an enum because it doesn&#39;t have two values, it has one value that you can view in two ways.<div><br></div><div>Therefore I would make an Angle struct, something like:<div><br></div><div>







<p class="gmail-p1">//: Angle struct instead of angle enum</p>
<p class="gmail-p2"><br></p>
<p class="gmail-p3"><span class="gmail-s1">import</span> Foundation</p>
<p class="gmail-p2"><br></p>
<p class="gmail-p3"><span class="gmail-s1">struct</span> Angle  {</p>
<p class="gmail-p3">    <span class="gmail-s1">static</span> <span class="gmail-s1">let</span> d2R = <span class="gmail-s2">Double</span>.<span class="gmail-s2">pi</span> / <span class="gmail-s3">180</span></p>
<p class="gmail-p4">    </p>
<p class="gmail-p3">    <span class="gmail-s1">static</span> <span class="gmail-s1">let</span> r2D = <span class="gmail-s3">180</span> / <span class="gmail-s2">Double</span>.<span class="gmail-s2">pi</span></p>
<p class="gmail-p4">    </p>
<p class="gmail-p3">    <span class="gmail-s1">private</span> <span class="gmail-s1">var</span> degs: <span class="gmail-s2">Double</span></p>
<p class="gmail-p4">    </p>
<p class="gmail-p3">    <span class="gmail-s1">var</span> degrees: <span class="gmail-s2">Double</span> {</p>
<p class="gmail-p3">        <span class="gmail-s1">return</span> <span class="gmail-s4">degs</span></p>
<p class="gmail-p3">    }</p>
<p class="gmail-p4">    </p>
<p class="gmail-p3">    <span class="gmail-s1">var</span> radians: <span class="gmail-s2">Double</span> {</p>
<p class="gmail-p3">        <span class="gmail-s1">return</span> <span class="gmail-s4">degs</span> * <span class="gmail-s4">Angle</span>.<span class="gmail-s4">d2R</span></p>
<p class="gmail-p3">    }</p>
<p class="gmail-p4">    </p>
<p class="gmail-p3">    <span class="gmail-s1">init</span>(degrees: <span class="gmail-s2">Double</span> = <span class="gmail-s3">0</span>) {</p>
<p class="gmail-p3">        <span class="gmail-s4">degs</span> = degrees.<span class="gmail-s5">truncatingRemainder</span>(dividingBy: <span class="gmail-s3">180</span>)</p>
<p class="gmail-p3">    }</p>
<p class="gmail-p4">    </p>
<p class="gmail-p3">    <span class="gmail-s1">init</span>(radians: <span class="gmail-s2">Double</span>) {</p>
<p class="gmail-p3">        <span class="gmail-s1">self</span>.<span class="gmail-s1">init</span>(degrees: radians * <span class="gmail-s4">Angle</span>.<span class="gmail-s4">r2D</span>)</p>
<p class="gmail-p3">    }</p>
<p class="gmail-p3">}</p>
<p class="gmail-p2"><br></p>
<p class="gmail-p5">extension<span class="gmail-s6"> </span><span class="gmail-s4">Angle</span><span class="gmail-s6">: </span><span class="gmail-s2">Hashable</span><span class="gmail-s6"> {</span></p>
<p class="gmail-p3">    <span class="gmail-s1">var</span> hashValue: <span class="gmail-s2">Int</span> {</p>
<p class="gmail-p3">        <span class="gmail-s1">return</span> <span class="gmail-s4">degs</span>.<span class="gmail-s2">hashValue</span></p>
<p class="gmail-p3">    }</p>
<p class="gmail-p4">    </p>
<p class="gmail-p3">    <span class="gmail-s1">static</span> <span class="gmail-s1">func</span> ==(lhs: <span class="gmail-s4">Angle</span>, rhs: <span class="gmail-s4">Angle</span>) -&gt; <span class="gmail-s2">Bool</span> {</p>
<p class="gmail-p3">        <span class="gmail-s1">return</span> lhs.<span class="gmail-s4">degs</span> == rhs.<span class="gmail-s4">degs</span></p>
<p class="gmail-p3">    }</p>
<p class="gmail-p3">}</p>
<p class="gmail-p2"><br></p>
<p class="gmail-p1"><span class="gmail-s1">extension</span><span class="gmail-s6"> </span><span class="gmail-s4">Angle</span>/*: FloatingPoint*/<span class="gmail-s6"> {</span></p>
<p class="gmail-p3">    <span class="gmail-s1">static</span> <span class="gmail-s1">func</span> +(lhs: <span class="gmail-s4">Angle</span>, rhs: <span class="gmail-s4">Angle</span>) -&gt; <span class="gmail-s4">Angle</span> {</p>
<p class="gmail-p3">        <span class="gmail-s1">return</span> <span class="gmail-s4">Angle</span>(degrees: lhs.<span class="gmail-s4">degs</span> + rhs.<span class="gmail-s4">degs</span>)</p>
<p class="gmail-p3">    }</p>
<p class="gmail-p4">    </p>
<p class="gmail-p3">    <span class="gmail-s1">static</span> <span class="gmail-s1">func</span> +=(lhs: <span class="gmail-s1">inout</span> <span class="gmail-s4">Angle</span>, rhs: <span class="gmail-s4">Angle</span>) {</p>
<p class="gmail-p3">        lhs.<span class="gmail-s4">degs</span> += rhs.<span class="gmail-s4">degs</span></p>
<p class="gmail-p3">        lhs.<span class="gmail-s4">degs</span> = lhs.<span class="gmail-s4">degs</span>.<span class="gmail-s5">truncatingRemainder</span>(dividingBy: <span class="gmail-s3">180</span>)</p>
<p class="gmail-p3">    }</p>
<p class="gmail-p4">    </p>
<p class="gmail-p1"><span class="gmail-s6">    </span>// Rest of FloatingPoint ...</p>
<p class="gmail-p3">}</p>
<p class="gmail-p2"><br></p>
<p class="gmail-p1">// Trig</p>
<p class="gmail-p5">extension<span class="gmail-s6"> </span><span class="gmail-s4">Angle</span><span class="gmail-s6"> {</span></p>
<p class="gmail-p3">    <span class="gmail-s1">var</span> sin: <span class="gmail-s2">Double</span> {</p>
<p class="gmail-p1"><span class="gmail-s6">        </span><span class="gmail-s1">return</span><span class="gmail-s6"> Foundation.</span><span class="gmail-s5">sin</span><span class="gmail-s6">(</span><span class="gmail-s4">radians</span><span class="gmail-s6">) </span>// Need to qualify name to stop name clash</p>
<p class="gmail-p3">    }</p>
<p class="gmail-p4">    </p>
<p class="gmail-p1"><span class="gmail-s6">    </span>// Other trig</p>
<p class="gmail-p3">}</p>
<p class="gmail-p2"><br></p>
<p class="gmail-p3"><span class="gmail-s1">let</span> a = <span class="gmail-s4">Angle</span>(degrees: <span class="gmail-s3">90</span>) <span class="gmail-s7">// 90</span></p>
<p class="gmail-p1"><span class="gmail-s4">a</span><span class="gmail-s6">.</span><span class="gmail-s4">radians</span><span class="gmail-s6"> </span>// pi / 2</p>
<p class="gmail-p6">a<span class="gmail-s6">.</span>sin<span class="gmail-s6"> </span><span class="gmail-s7">// 1</span></p>
<p class="gmail-p3"><span class="gmail-s1">let</span> b = <span class="gmail-s4">Angle</span>(radians: <span class="gmail-s3">3</span>) <span class="gmail-s7">// Almost pi</span></p>
<p class="gmail-p6">b<span class="gmail-s6">.</span>degrees<span class="gmail-s6"> </span><span class="gmail-s7">// 171.9</span></p>
<p class="gmail-p1"><span class="gmail-s1">let</span><span class="gmail-s6"> c = </span><span class="gmail-s4">a</span><span class="gmail-s6"> + </span><span class="gmail-s4">b</span><span class="gmail-s6"> </span>// Wraps over 180 degrees</p>
<p class="gmail-p6">c<span class="gmail-s6">.</span>degrees<span class="gmail-s6"> </span><span class="gmail-s7">// 81.9</span></p>
<p class="gmail-p1"><span class="gmail-s4">c</span><span class="gmail-s6"> == </span><span class="gmail-s4">b</span><span class="gmail-s6"> </span>// false</p>
<p class="gmail-p6">c<span class="gmail-s6">.</span>hashValue<span class="gmail-s6"> </span><span class="gmail-s7">// 463...</span></p>
<p class="gmail-p3"><span class="gmail-s1">let</span> d = <span class="gmail-s4">Angle</span>(degrees: <span class="gmail-s3">-90</span>) <span class="gmail-s7">// -90</span></p>
<p class="gmail-p1"><span class="gmail-s4">d</span><span class="gmail-s6">.</span><span class="gmail-s4">radians</span><span class="gmail-s6"> </span>// -pi / 2</p>
<p class="gmail-p3"><span class="gmail-s1">var</span> e = <span class="gmail-s4">Angle</span>(radians: <span class="gmail-s3">-3</span>) <span class="gmail-s7">// Almost -pi</span></p>
<p class="gmail-p1"><span class="gmail-s4">e</span><span class="gmail-s6">.</span><span class="gmail-s4">degrees</span><span class="gmail-s6"> </span>// -171.9</p>
<p class="gmail-p1"><span class="gmail-s4">e</span><span class="gmail-s6"> += </span><span class="gmail-s4">d</span><span class="gmail-s6"> </span>// Wraps over -180 degrees</p>
<p class="gmail-p6">e<span class="gmail-s6">.</span>degrees<span class="gmail-s6"> </span><span class="gmail-s7">// -81.9</span></p></div></div></div><div class="gmail_extra"><br clear="all"><div><div class="gmail_signature" data-smartmail="gmail_signature">  -- Howard.<br></div></div>
<br><div class="gmail_quote">On 19 June 2017 at 13:32, David Sweeris via swift-users <span dir="ltr">&lt;<a href="mailto:swift-users@swift.org" target="_blank">swift-users@swift.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto"><span class=""><div><br></div><div>On Jun 18, 2017, at 19:30, Nevin Brackett-Rozinsky via swift-users &lt;<a href="mailto:swift-users@swift.org" target="_blank">swift-users@swift.org</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><div dir="ltr">Is there a way to restrict the associated values of an enum? For example, suppose I have this type:<div><br></div><div><div><font face="monospace, monospace">enum Angle {</font></div><div><font face="monospace, monospace">    case radians(Double)</font></div><div><font face="monospace, monospace">    case degrees(Double)</font></div><div><font face="monospace, monospace">}</font></div></div><div><br></div><div>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).</div><div><br></div><div>I don’t see a way to do it. Is this possible?<br></div><div><br></div><div>The closest I’ve found is to create auxiliary types such as</div><div><br></div><div><font face="monospace, monospace">struct Degree { … }</font></div><div><font face="monospace, monospace">struct Radian { … }</font><br></div><div><br></div><div>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.</div><div><br></div><div>Is there a better way?</div></div></div></blockquote><br></span><div>Not off the top of my head, at least not without changing the syntax.</div><div><br></div><div>You could add two inits, with different argument labels, and not directly set the case: <span style="background-color:rgba(255,255,255,0)">“let x = Angle(degrees: -45)”</span></div><div><br></div><div>You could add &quot;public var radians: Double { get {...} set {...} }&quot; (and again for &quot;degrees&quot;) to `Angle`. The getter would need to<span style="background-color:rgba(255,255,255,0)"> switch on self to figure out if you need to convert between the two (like if someone said &quot;.radians(2).degrees&quot;): “var x = Angle.radians(0); x.degrees = -45&quot;</span></div><div><br></div><div><span style="background-color:rgba(255,255,255,0)">Alternately, you could add &quot;subscript() -&gt; Double&quot; 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&quot;</span></div><div><span style="background-color:rgba(255,255,255,0)"><br></span></div><div><span style="background-color:rgba(255,255,255,0)">Hope that helps</span></div><div><span style="background-color:rgba(255,255,255,0)">- Dave Sweeris </span></div></div><br>______________________________<wbr>_________________<br>
swift-users mailing list<br>
<a href="mailto:swift-users@swift.org">swift-users@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-users" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-users</a><br>
<br></blockquote></div><br></div>