<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div></div><div><br></div><div><br>On Jan 15, 2018, at 3:30 PM, Karl Wagner &lt;<a href="mailto:razielim@gmail.com">razielim@gmail.com</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On 14. Jan 2018, at 21:12, Kelvin Ma via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class="">This could work, but you’re also giving up all the nice Numeric and FloatingPoint conformances when you use this,, all of a sudden adding two angles together isn’t let <span style="font-family:monospace,monospace" class="">γ = α + β</span>, it’s <span style="font-family:monospace,monospace" class="">γ = Angle.radians(α.radians + β.radians)</span>. just no. at the risk of blowing up the scope of this idea, dedicated <span style="font-family:monospace,monospace" class="">Angle</span> types also begs for generic trigonometric functions like <span style="font-family:monospace,monospace" class="">Angle.sin(_:)</span> and <span style="font-family:monospace,monospace" class="">Angle.cos(_:)</span>. i proposed that a while back and even tried implementing it but fast trig evaluation doesn’t genericize well since it relies a lot on <span style="font-family:monospace,monospace" class="">rsqrt</span>-style magic constants<br class=""></div></div></div></blockquote><div><br class=""></div><div>You could add those conformances back, if you wanted. Most low-level trig code will quickly escape the wrapper once it starts using the values. Mostly I use it as a currency type and for converting untyped angles. I think it’s a great example of Swift’s zero-cost abstractions - we added semantic meaning (this value isn’t just a number with a specific bit representation, it’s a number which represents a specific kind of quantity), and encapsulated some useful functionality, and we don't lose any performance.</div><div><br class=""></div><div>I have a couple of these, such as Distance&lt;T&gt; and Time (wraps a TimeInterval). This allows me to write algorithms like:</div><div><br class=""></div><div>&nbsp; &nbsp;&nbsp;public&nbsp;func&nbsp;point(_ distance:&nbsp;Distance&lt;Double&gt;, along bearing:&nbsp;Angle&lt;Double&gt;) -&gt;&nbsp;Geo.Point</div><div><br class=""></div><div>And use it like this:</div><div><br class=""></div><div>&nbsp; &nbsp; let nextPlace = thisPlace.point(.kilometers(42), along: .degrees(45))</div><div><br class=""></div><div>Or this:</div><div><br class=""></div><div>&nbsp; &nbsp; let nextPlace = thisPlace.point(.miles(500), along: .radians(.pi/2))</div><div><br class=""></div><div>And so my algorithm actually becomes quite difficult to use incorrectly. Also, that’s why I use static constructors; similar to how lots of OptionSet types are implemented, doing it this way lets you use an enum-like syntax to create values, which fits Angle’s intended use as a parameter/return type.</div><div><br class=""></div><div>I’m not saying this should be part of the standard library (this isn’t my pitch), I’m just saying these kind of wrappers are useful when creating good APIs. I think somebody was dismissing the idea of an Angle&lt;T&gt; type in general before.</div><div><br class=""></div><div>- Karl</div></div></div></blockquote><div><br></div><div>i thought the whole thing with resiliency barriers is that these kinds of abstractions are *not* zero cost anymore, accessing a member of an imported struct is always going to be through an indirect getter and setter. &amp;&amp; this doesn’t get fixed by slava’s inlineable thing because you can’t “inline” a struct layout</div><br><blockquote type="cite"><div><div><div><br class=""></div><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class=""><br class=""></div>also, why are <span style="font-family:monospace,monospace" class="">radians(_:)</span> and <span style="font-family:monospace,monospace" class="">degrees(_:)</span> static functions? i really only use static constructors for initializers that have side effects<br class=""></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Sun, Jan 14, 2018 at 6:36 AM, Karl Wagner <span dir="ltr" class="">&lt;<a href="mailto:razielim@gmail.com" target="_blank" class="">razielim@gmail.com</a>&gt;</span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space" class=""><br class=""><div class=""><span class=""><br class=""><blockquote type="cite" class=""><div class="">On 14. Jan 2018, at 09:51, Taylor Swift via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="m_-671662914338481272Apple-interchange-newline"><div class=""><div dir="auto" class=""><div class=""></div><div class="">I do a lot of geometry and spherical-related work and i have never found an Angle type to be worth having. Always use radians. It’s what sin() and cos() take, it’s what graphics APIs like Cairo expect, it’s what graphics formats like SVG use. plus,, do you *really* want to be case-branching on every angle value? that really adds up when you’re converting 100,000s of lat-long pairs to cartesian.</div></div></div></blockquote><div class=""><br class=""></div></span><div class="">You can do it without case-branching. I too have an Angle type; this is what I use:</div><div class=""><br class=""></div><div class=""><div style="margin:0px;font-stretch:normal;font-size:16px;line-height:normal;font-family:&quot;Fira Code&quot;;color:rgb(231,232,235);background-color:rgb(41,43,54)" class=""><span style="color:#e12da0" class="">public</span> <span style="color:#e12da0" class="">struct</span> Angle&lt;T: <span style="color:#29a09f" class="">FloatingPoint</span>&gt; {</div><div style="margin:0px;font-stretch:normal;font-size:16px;line-height:normal;font-family:&quot;Fira Code&quot;;color:rgb(231,232,235);background-color:rgb(41,43,54)" class="">&nbsp; <span style="color:#e12da0" class="">public</span> <span style="color:#e12da0" class="">var</span> radians: <span style="color:#18b5b1" class="">T</span></div><div style="margin:0px;font-stretch:normal;font-size:16px;line-height:normal;font-family:&quot;Fira Code&quot;;color:rgb(231,232,235);background-color:rgb(41,43,54)" class="">&nbsp; <span style="color:#e12da0" class="">public</span> <span style="color:#e12da0" class="">var</span> degrees: <span style="color:#18b5b1" class="">T</span> {</div><div style="margin:0px;font-stretch:normal;font-size:16px;line-height:normal;font-family:&quot;Fira Code&quot;;color:rgb(231,232,235);background-color:rgb(41,43,54)" class="">&nbsp; &nbsp; <span style="color:#e12da0" class="">return</span> (<span style="color:#18b5b1" class="">radians</span> / .<span style="color:#29a09f" class="">pi</span>) * <span style="color:#00aaa3" class="">180</span></div><div style="margin:0px;font-stretch:normal;font-size:16px;line-height:normal;font-family:&quot;Fira Code&quot;;color:rgb(231,232,235);background-color:rgb(41,43,54)" class="">&nbsp; }</div><div style="margin:0px;font-stretch:normal;line-height:normal;background-color:rgb(41,43,54);min-height:14px" class=""><br class=""></div><div style="margin:0px;font-stretch:normal;font-size:16px;line-height:normal;font-family:&quot;Fira Code&quot;;color:rgb(231,232,235);background-color:rgb(41,43,54)" class="">&nbsp; <span style="color:#e12da0" class="">public</span> <span style="color:#e12da0" class="">static</span> <span style="color:#e12da0" class="">func</span> radians(<span style="color:#e12da0" class="">_</span> rads: <span style="color:#18b5b1" class="">T</span>) -&gt; <span style="color:#18b5b1" class="">Angle</span> {</div><div style="margin:0px;font-stretch:normal;font-size:16px;line-height:normal;font-family:&quot;Fira Code&quot;;color:rgb(231,232,235);background-color:rgb(41,43,54)" class="">&nbsp; &nbsp; <span style="color:#e12da0" class="">return</span> <span style="color:#18b5b1" class="">Angle</span>(radians: rads)</div><div style="margin:0px;font-stretch:normal;font-size:16px;line-height:normal;font-family:&quot;Fira Code&quot;;color:rgb(231,232,235);background-color:rgb(41,43,54)" class="">&nbsp; }</div><div style="margin:0px;font-stretch:normal;font-size:16px;line-height:normal;font-family:&quot;Fira Code&quot;;color:rgb(231,232,235);background-color:rgb(41,43,54)" class="">&nbsp; <span style="color:#e12da0" class="">public</span> <span style="color:#e12da0" class="">static</span> <span style="color:#e12da0" class="">func</span> degrees(<span style="color:#e12da0" class="">_</span> degs: <span style="color:#18b5b1" class="">T</span>) -&gt; <span style="color:#18b5b1" class="">Angle</span> {</div><div style="margin:0px;font-stretch:normal;font-size:16px;line-height:normal;font-family:&quot;Fira Code&quot;;color:rgb(231,232,235);background-color:rgb(41,43,54)" class="">&nbsp; &nbsp; <span style="color:#e12da0" class="">return</span> <span style="color:#18b5b1" class="">Angle</span>(radians: (degs / <span style="color:#00aaa3" class="">180</span>) * .<span style="color:#29a09f" class="">pi</span>)</div><div style="margin:0px;font-stretch:normal;font-size:16px;line-height:normal;font-family:&quot;Fira Code&quot;;color:rgb(231,232,235);background-color:rgb(41,43,54)" class="">&nbsp; }</div><div style="margin:0px;font-stretch:normal;font-size:16px;line-height:normal;font-family:&quot;Fira Code&quot;;color:rgb(231,232,235);background-color:rgb(41,43,54)" class="">}</div></div><div class=""><br class=""></div>If you ask for “radians” (like most low-level trig code will), you just get the stored property. The conversion “overhead” is only done at construction time, so it makes a convenient parameter/return value.</div><span class="HOEnZb"><font color="#888888" class=""><div class=""><br class=""></div><div class="">- Karl</div></font></span><div class=""><div class="h5"><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div dir="auto" class=""><div class=""><br class="">On Jan 14, 2018, at 12:04 AM, BJ Homer via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class=""></div><blockquote type="cite" class=""><div class="">An Angle type already exists in Foundation; see Measurement&lt;UnitAngle&gt;. You could add some convenience methods in an extension pretty easily.<div class=""><br class=""></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px" class=""><div class=""><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)" class=""><span style="color:#ba2da2" class="">import</span> Foundation</div></div><div class=""><div style="margin:0px;font-stretch:normal;font-size:12px;line-height:normal;background-color:rgb(255,255,255);min-height:14px" class=""><br class=""></div></div><div class=""><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(112,61,170);background-color:rgb(255,255,255)" class=""><span style="color:#ba2da2" class="">typealias</span><span class=""> Angle = </span>Measurement<span class="">&lt;</span>UnitAngle<span class="">&gt;</span></div></div><div class=""><div style="margin:0px;font-stretch:normal;font-size:12px;line-height:normal;background-color:rgb(255,255,255);min-height:14px" class=""><br class=""></div></div><div class=""><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)" class=""><span style="color:#ba2da2" class="">extension</span> <span style="color:#703daa" class="">Measurement</span> <span style="color:#ba2da2" class="">where</span> UnitType == UnitAngle {</div></div><div class=""><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)" class="">&nbsp; &nbsp; <span style="color:#ba2da2" class="">var</span> sine: <span style="color:#703daa" class="">Double</span> {</div></div><div class=""><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#ba2da2" class="">let</span> radians = <span style="color:#ba2da2" class="">self</span>.<span style="color:#3e1e81" class="">converted</span>(to: .<span style="color:#703daa" class="">radians</span>).<span style="color:#703daa" class="">value</span></div></div><div class=""><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#ba2da2" class="">return</span> <span style="color:#3e1e81" class="">sin</span>(radians)</div></div><div class=""><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)" class="">&nbsp; &nbsp; }</div></div><div class=""><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255); min-height: 13px;" class="">&nbsp;&nbsp; &nbsp;<br class="m_-671662914338481272webkit-block-placeholder"></div></div><div class=""><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)" class="">&nbsp; &nbsp; <span style="color:#ba2da2" class="">static</span> <span style="color:#ba2da2" class="">var</span> threeQuarterTurn: <span style="color:#4f8187" class="">Angle</span> {</div></div><div class=""><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#ba2da2" class="">return</span> <span style="color:#4f8187" class="">Angle</span>(value: <span style="color:#272ad8" class="">0.75</span>, unit: .<span style="color:#703daa" class="">revolutions</span>)</div></div><div class=""><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)" class="">&nbsp; &nbsp; }</div></div><div class=""><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)" class="">}</div></div><div class=""><div style="margin:0px;font-stretch:normal;font-size:12px;line-height:normal;background-color:rgb(255,255,255);min-height:14px" class=""><br class=""></div></div><div class=""><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(79,129,135);background-color:rgb(255,255,255)" class=""><span style="color:#ba2da2" class="">let</span><span class=""> x = </span>Angle<span class="">.</span>threeQuarterTurn</div></div><div class=""><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(79,129,135);background-color:rgb(255,255,255)" class="">x<span class="">.</span>sine<span class=""> </span><span style="color:#008400" class="">// -1</span></div></div></blockquote><div class=""><div class=""><br class=""></div><div class="">-BJ</div><div class=""><br class=""></div><div class=""><br class=""><blockquote type="cite" class=""><div class="">On Jan 13, 2018, at 9:31 PM, Erica Sadun via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="m_-671662914338481272Apple-interchange-newline"><div class=""><div style="word-wrap:break-word;line-break:after-white-space" class="">I would like to see a full Geometry implementation but I don't think it should be part of the standard library.<div class=""><br class=""></div><div class="">I've kicked around some ideas here:&nbsp;</div><div class=""><br class=""></div><div class="">*&nbsp;<a href="https://gist.github.com/erica/8cb4b21cf0c429828fad1d8ad459b71b" target="_blank" class="">https://gist.github.com/<wbr class="">erica/<wbr class="">8cb4b21cf0c429828fad1d8ad459b7<wbr class="">1b</a></div><div class="">*&nbsp;<a href="https://gist.github.com/erica/ee06008202c9fed699bfa6254c42c721" target="_blank" class="">https://gist.github.com/<wbr class="">erica/<wbr class="">ee06008202c9fed699bfa6254c42c7<wbr class="">21</a></div><div class=""><br class=""></div><div class="">and</div><div class=""><br class=""></div><div class="">*&nbsp;<a href="https://github.com/erica/SwiftGeometry" target="_blank" class="">https://github.com/erica/<wbr class="">SwiftGeometry</a><br class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">On Jan 13, 2018, at 7:49 PM, Jonathan Hull via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="m_-671662914338481272Apple-interchange-newline"><div class=""><div style="word-wrap:break-word" class="">Hi Evolution,<div class=""><br class=""></div><div class="">I would <i class="">really</i> like to see Swift gain an Angle type in the standard library.&nbsp; Every time I have to deal with an angle in an api, I have to go figure out the conventions for that call.&nbsp; Is it in degrees? Is it in radians?&nbsp; What if it is in radians, but I want to think about it in degrees?</div><div class=""><br class=""></div><div class="">I ended up writing an Angle type for my own code a few years back, and I have to say it is really wonderful.&nbsp; It has greatly simplified my graphics work.&nbsp; It takes a lot of mental load off of my brain when dealing with Angles.</div><div class=""><br class=""></div><div class="">I can of course initialize it either as degrees or radians (or revolutions), but I can also just say things like ‘.threeQuarterTurn’, and then I can get the value back out in whatever format I like.&nbsp; There are also useful additions that let me normalize the angle to different ranges and which let me snap to the nearest multiple of an angle. Both of these are enormously useful for user facing features.&nbsp; I can also do math on angles in a way that makes geometric sense for angles.&nbsp; It is also really useful for interacting with CGVectors in intelligent ways.</div><div class=""><br class=""></div><div class="">Using Doubles or CGFloats to represent angles everywhere is just semantically wrong IMHO, and it stops us from adding all of these angle-specific niceties.</div><div class=""><br class=""></div><div class="">Happy to provide code if there is interest…</div><div class=""><br class=""></div><div class="">Thanks,</div><div class="">Jon</div></div>______________________________<wbr class="">_________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-<wbr class="">evolution</a><br class=""></div></blockquote></div><br class=""></div></div>______________________________<wbr class="">_________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-<wbr class="">evolution</a><br class=""></div></blockquote></div><br class=""></div></div></blockquote><blockquote type="cite" class=""><div class=""><span class="">______________________________<wbr class="">_________________</span><br class=""><span class="">swift-evolution mailing list</span><br class=""><span class=""><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a></span><br class=""><span class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-<wbr class="">evolution</a></span><br class=""></div></blockquote></div>______________________________<wbr class="">_________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-<wbr class="">evolution</a><br class=""></div></blockquote></div><br class=""></div></div></div></blockquote></div><br class=""></div>
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote></div><br class=""></div></blockquote></body></html>