<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Hey Sean,</div><div class=""><br class=""></div><div class="">+ 1</div><div class=""><br class=""></div>That’s indeed very similar, I must have overlooked your email in the flood of emails at the time.<div class=""><br class=""></div><div class="">Especially</div><div class=""><br class=""></div><div class=""><div class=""></div><blockquote type="cite" class=""><div class="">I like the idea of this always being a compile-time check when possible, but it could also be useful to force the requirement to be evaluated at runtime by adding a force operator to it:</div><div class=""><br class=""></div><div class="">func scale(x: Float in! 0…1) -&gt; Float {</div><div class="">&nbsp; return someValue * x</div><div class="">}</div></blockquote></div><div class=""><div class=""></div><blockquote type="cite" class=""><div class="">In this scenario the compiler would probably still try to prove it statically - and if it could, it’d skip runtime checks - but if it cannot, it would then insert runtime guards that catch requirement failures and crash as necessary - similar to a forced unwrap - instead of being a compile time error.</div></blockquote><br class=""></div><div class="">The reasons I think `in` isn’t the best choice for this keyword are</div><div class=""><br class=""></div><div class="">- `in` already is a keyword with a totally different meaning</div><div class="">- a range is just an example of such a predicate, here are some examples (using the `Type` version of my last email, though I think the name doesn’t make much sense, we’re refining the type, yes, but the calculation in the predicate is applied to an instance of that type 🤔):</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">&nbsp; &nbsp; typealias</span><span style="font-variant-ligatures: no-common-ligatures" class=""> RGBAInt = </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Int</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">where</span><span style="font-variant-ligatures: no-common-ligatures" class=""> Type &gt;= </span><span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">0</span><span style="font-variant-ligatures: no-common-ligatures" class=""> &amp;&amp; Type &lt;= </span><span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">255</span><span style="font-variant-ligatures: no-common-ligatures" class=""> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span style="font-variant-ligatures: no-common-ligatures; color: #008400" class="">// Can be rewritten as a range (0...255)</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">&nbsp; &nbsp; typealias</span><span style="font-variant-ligatures: no-common-ligatures" class=""> RGBADouble = </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Double</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">where</span><span style="font-variant-ligatures: no-common-ligatures" class=""> Type &gt;= </span><span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">0</span><span style="font-variant-ligatures: no-common-ligatures" class=""> &amp;&amp; Type &lt;= </span><span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">1.0</span><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #008400" class="">// Can be rewritten as a range (0...1.0)</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">&nbsp; &nbsp; typealias</span><span style="font-variant-ligatures: no-common-ligatures" class=""> BatteryLevel = </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Int</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">where</span><span style="font-variant-ligatures: no-common-ligatures" class=""> Type &gt;= </span><span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">0</span><span style="font-variant-ligatures: no-common-ligatures" class=""> &amp;&amp; Type &lt;= </span><span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">100</span><span style="font-variant-ligatures: no-common-ligatures" class=""> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #008400" class="">// Can be rewritten as a range (0...100)</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">&nbsp; &nbsp; typealias</span><span style="font-variant-ligatures: no-common-ligatures" class=""> Primes10 = </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Int</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">where</span><span style="font-variant-ligatures: no-common-ligatures" class=""> Type == </span><span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">2</span><span style="font-variant-ligatures: no-common-ligatures" class=""> || Type == </span><span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">3</span><span style="font-variant-ligatures: no-common-ligatures" class=""> || Type == </span><span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">5</span><span style="font-variant-ligatures: no-common-ligatures" class=""> || Type == </span><span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">7</span><span style="font-variant-ligatures: no-common-ligatures" class=""> &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #008400" class="">// Cannot be rewritten as a range</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #008400" class="">&nbsp; &nbsp;&nbsp;</span><span style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);" class="">typealias</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> EvenNumber = </span><span style="font-variant-ligatures: no-common-ligatures; color: rgb(112, 61, 170);" class="">Int</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);" class="">where</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> Type % </span><span style="font-variant-ligatures: no-common-ligatures; color: rgb(39, 42, 216);" class="">2</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> == </span><span style="font-variant-ligatures: no-common-ligatures; color: rgb(39, 42, 216);" class="">0</span><span style="font-variant-ligatures: no-common-ligatures;" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: rgb(0, 132, 0);" class="">// Cannot be rewritten as a range</span></div><div class=""><span style="color: rgb(39, 42, 216);" class="">&nbsp;&nbsp;</span></div><div class="">What do you think?</div><div class=""><br class=""></div><div class="">- Dennis</div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Jan 15, 2016, at 4:41 PM, Sean Heber &lt;<a href="mailto:sean@fifthace.com" class="">sean@fifthace.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">I had a similar idea in the early days of the mailing list before I knew it had a name. I don’t think it got much (any, really) discussion at the time: <a href="https://lists.swift.org/pipermail/swift-evolution/2015-December/000022.html" class="">https://lists.swift.org/pipermail/swift-evolution/2015-December/000022.html</a><br class=""><br class="">l8r<br class="">Sean<br class=""><br class=""><br class=""><blockquote type="cite" class="">On Jan 15, 2016, at 8:53 AM, Dennis Weissmann via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class=""><blockquote type="cite" class=""><br class="">On Jan 15, 2016, at 1:56 PM, Haravikk &lt;<a href="mailto:swift-evolution@haravikk.com" class="">swift-evolution@haravikk.com</a>&gt; wrote:<br class=""><br class="">This is pretty interesting; while the actual compile-time type-checking could be complex and take some time to implement, it seems to me that the actual notation could be implemented in advance and simply perform runtime assertions until the real type-checking is ready? In cases where the type-checker can’t be certain of a value’s safety, a run-time assertion might make sense anyway, so this short-term behaviour could actually be left in, with the caveat being that your restriction could still fail at run-time (which is what I think most people would want when the compile-time check isn’t enough).<br class=""><br class=""></blockquote><br class="">That’s an interesting approach! I like it :)<br class=""><br class=""><blockquote type="cite" class="">I’d be particularly interested in getting the notation available sooner if it's concise enough to make it worth using in place of current if statements. For example, it’d be nice if there were some shorthand for integers, as these seem like they’d be a particularly common use-case, for example:<br class=""><br class="">var @where(“0 &lt;= myVariable &lt;= 100”) myVariable = 42<br class="">var @where(“0 &lt;= $1 &lt;= 100) myVariable = 42<br class=""><br class="">Though personally I’d prefer something even more concise like:<br class=""><br class="">var myVariable(0…100) = 42<br class="">var myVariable:Int(0…100) = 42<br class=""><br class=""></blockquote><br class="">I don’t like the @where syntax too much either (but I don’t have the time right now to come up with a better, well-thought-out and practical syntax myself).<br class="">Here are just some quick thoughts:<br class=""><br class="">// Annotating the type<br class="">let value: Int&lt;1...100&gt; = 42 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Generics?<br class="">let value: Int(1...100) = 42 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Initializer?<br class="">let value: Int{1...100} = 42 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Scope?<br class="">let value: {value: Int | 1...100} = 42 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// LiquidHaskell<br class="">let value: Int where Type == 1...100 = 42 &nbsp;&nbsp;// `where` already is a keyword that acts very similar (but at runtime)<br class=""><br class="">// Annotating the variable (the inferred type)<br class="">let value&lt;1...100&gt; = 42<br class="">let value(1...100) = 42<br class="">let value{1...100} = 42<br class="">let value{value: Int | 1...100} = 42<br class="">let value where Type == 1...100 = 42<br class=""><br class="">Even though it is more verbose, I like the last approach best. I think the common use-case is to predefine some very common ones (e.g. RGBA) in typealiases like so:<br class=""><br class="">typealias RGBAValue = Int where Type == 0...255<br class=""><br class="">This makes it much nicer (IMO) to declare (e.g.) functions. `UIColor` for example could gain an initializer taking values from 0 to 255:<br class=""><br class="">init(red: RGBAValue, green: RGBAValue, blue: RGBAValue, alpha: RGBAValue)<br class=""><br class=""><blockquote type="cite" class="">Leaving the @where clause for more complex (i.e- non-numeric) cases. A really powerful alternative would be to allow us some mechanism to define how to handle restrictions in our classes and structs; these would be compiled first so that they can be executed by the type checker (which may limit what they can do) but could allow us full control of how they work. So, for example, an integer definition might look like:<br class=""><br class="">struct Int… {<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>...<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>restriction(range:Range&lt;Int&gt;) -&gt; Bool { return range.contains(self) }<br class="">}<br class="">var myVariable(0…100) = 42<br class=""><br class="">At run-time this would be equivalent to:<br class=""><br class="">var myVariable = 42<br class="">assert(myVariable.restriction(0…100), “Value of myVariable is out of bounds [0…100]”)<br class=""><br class="">With the idea being that in future the type-checker would call the restriction check, find 42 to be in range and omit the assertion entirely.<br class=""><br class="">Just some thoughts, but the main thing for me is that this is something that I’d like to use a lot if implemented, so the more concise it can be, the better.<br class=""><br class=""></blockquote>Exactly :) If the type is precise enough the compiler can actually write (infer) a lot of your code)<br class=""><br class=""><blockquote type="cite" class="">- Haravikk<br class=""><br class=""><blockquote type="cite" class="">On 15 Jan 2016, at 12:27, Dennis Weissmann via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class=""><blockquote type="cite" class="">On Jan 15, 2016, at 6:53 AM, Dave via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class="">This is the same thing as Refinement Types, right?<br class=""><a href="https://en.wikipedia.org/wiki/Refinement_(computing)#Refinement_types" class="">https://en.wikipedia.org/wiki/Refinement_(computing)#Refinement_types</a><br class="">http://goto.ucsd.edu/~rjhala/liquid/haskell/blog/blog/2013/01/01/refinement-types-101.lhs/<br class=""><br class=""></blockquote><br class="">Yes, it seems they are. There is a pretty nice and easy to understand explanation [here](<a href="https://github.com/tomprimozic/type-systems/tree/master/refined_types" class="">https://github.com/tomprimozic/type-systems/tree/master/refined_types</a>):<br class=""><br class="">Refined types or contracts are a restricted form of dependent types that combine base datatypes with logical predicates; for example, the type of natural numbers could be written x : int if x ≥ 0 (the notation most commonly used in academic literature is {ν : int | ν ≥ 0}).<br class=""><br class=""><blockquote type="cite" class="">I’m in favor of it, but I think someone’s already made that suggestion… At the very least, I didn’t know what the phrase meant until a few days ago, and I know I learned about it from reading something on swift-evolution.<br class=""></blockquote><br class="">That was probably Matthew (<a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160104/005925.html" class="">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160104/005925.html</a>) or me (<a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160104/005918.html" class="">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160104/005918.html</a>) - the thread is called 'Proposal: named invariants for variable declarations'<br class=""><br class="">And I agree with Matthew that this won’t happen anytime soon. That’s why I didn’t want to discuss that topic too much. It’s just that the ABI will be finalized later this year and I wanted to mention that there is definitely interest in this area in case some ABI-related things are needed for refinement types (or even dependent types, someday, one can dream 😇) which need to be thought of before the finalization.<br class=""><br class="">- Dennis<br class=""><br class=""><blockquote type="cite" class="">- Dave Sweeris<br class=""><br class=""><blockquote type="cite" class="">On Jan 14, 2016, at 20:32, Suminda Dharmasena via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class="">E.g. <br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• var @where("myVariable &lt;= 100 &amp;&amp; myVariable &gt;= 0") myVariable = 42<br class=""><br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• @where("myVariable &lt;= 80 &amp;&amp; myVariable &gt;= 50")<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• {<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• &nbsp;&nbsp;&nbsp;&nbsp;...<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• }<br class=""><br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• @where("score &lt;= 100 &amp;&amp; score &gt;= 0")<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• for score in individualScores {<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• &nbsp;&nbsp;&nbsp;&nbsp;...<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• }<br class=""> _______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></blockquote><br class=""> _______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></blockquote><br class=""><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></blockquote><br class=""></blockquote><br class=""> _______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></blockquote><br class=""></div></div></blockquote></div><br class=""></div></body></html>