<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="">I like the principle in general, but I have some concerns about the range syntax. Firstly my concern is that allowing either end of the range to be omitted feels like a possible bug to me, so I'm not sure if we should encourage that?</div><div class=""><br class=""></div><div class="">I'm wondering if a slightly better alternative might to be to retain the operators as binary but to pass Void, like so:</div><div class=""><br class=""></div><div class=""><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let rangeFrom = 5...()</font></div><div class=""><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let rangeTo = ()...5</font></div><div class=""><br class=""></div><div class="">And so-on. It's not quite as pretty, but makes it clear that no mistake was made, and allows the operators to be defined normally taking two arguments of Comparable and Void (and vice versa).</div><div class=""><br class=""></div><div class="">It could be neatened up if we could allow a lone underscore as Void, like so:</div><div class=""><br class=""></div><div class=""><div class=""><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let rangeFrom = 5..._</font></div><div class=""><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let rangeTo = _...5</font></div></div><div class=""><br class=""></div><div class="">This is a bit neater looking, and should be consistent with how underscore is used elsewhere? I'm not sure if it might conflict though, but I don't think so.</div><div class=""><br class=""></div><div class="">Just I thought, but I dislike the idea that by forgetting a value on a range, or making some other typo, I could accidentally define an open ended range and change the behaviour of something that accepts both open and closed ranges, I think requiring <b class="">something</b>&nbsp;that explicitly indicates an open range is a bit better.</div><br class=""><div><blockquote type="cite" class=""><div class="">On 12 Apr 2017, at 17:40, Ben Cohen 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=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Hi Swift community,<div class=""><br class=""></div><div class="">Another proposal pitch. These operators were mentioned briefly in the String manifesto as prefixing/suffixing is very common with strings.</div><div class=""><br class=""></div><div class="">Online copy here:&nbsp;<a href="https://github.com/airspeedswift/swift-evolution/blob/71b819d30676c44234bac1aa999961fc5c39bcf3/proposals/NNNN-OneSidedRanges.md" class="">https://github.com/airspeedswift/swift-evolution/blob/71b819d30676c44234bac1aa999961fc5c39bcf3/proposals/NNNN-OneSidedRanges.md</a></div><div class=""><h1 id="one-sided-ranges" style="font-size: 37px; line-height: 42px; margin-top: 42px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;" class="">One-sided Ranges</h1><ul style="margin-top: 21px; margin-bottom: 21px; padding-left: 1.5em; color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 11.999999046325684px;" class=""><li style="font-size: 13.19999885559082px;" class="">Proposal:&nbsp;<a href="file:///Users/ben_cohen/Documents/swift-evolution/proposals/NNNN-filename.md" style="color: rgb(13, 110, 161); text-decoration: none; transition: color 0.2s ease-in-out;" class="">SE-NNNN</a></li><li style="font-size: 13.19999885559082px;" class="">Authors:&nbsp;<a href="https://github.com/airspeedswift" style="color: rgb(13, 110, 161); text-decoration: none; transition: color 0.2s ease-in-out;" class="">Ben Cohen</a>,&nbsp;<a href="https://github.com/dabrahams" style="color: rgb(13, 110, 161); text-decoration: none; transition: color 0.2s ease-in-out;" class="">Dave Abrahams</a>,&nbsp;<a href="https://github.com/brentdax" style="color: rgb(13, 110, 161); text-decoration: none; transition: color 0.2s ease-in-out;" class="">Brent Royal-Gordon</a></li><li style="font-size: 13.19999885559082px;" class="">Review Manager: TBD</li><li style="font-size: 13.19999885559082px;" class="">Status:&nbsp;<strong style="line-height: 1;" class="">Awaiting review</strong></li></ul><h2 id="introduction" style="color: rgb(17, 17, 17); font-size: 27px; line-height: 42px; margin-top: 42px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;" class="">Introduction</h2><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">This proposal introduces the concept of a “one-sided” range, created via prefix/postfix versions of the existing range operators.</p><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">It also introduces a new protocol,&nbsp;<code style="line-height: 1;" class="">RangeExpression</code>, to simplify the creation of methods that take different kinds of ranges.</p><h2 id="motivation" style="color: rgb(17, 17, 17); font-size: 27px; line-height: 42px; margin-top: 42px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;" class="">Motivation</h2><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">It is common, given an index into a collection, to want a slice up to or from that index versus the start/end.</p><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">For example (assuming&nbsp;<code style="line-height: 1;" class="">String</code>&nbsp;is once more a&nbsp;<code style="line-height: 1;" class="">Collection</code>):</p><pre style="margin-top: 21px; margin-bottom: 21px; tab-size: 4; color: rgb(17, 17, 17); font-size: 11.999999046325684px; height: 60px; background-color: rgb(248, 248, 248);" class=""><code class="swift hljs" style="line-height: inherit; display: block; overflow-x: auto; padding: 0.5em; color: rgb(51, 51, 51); height: auto;"><span class="hljs-keyword" style="font-weight: bold;">let</span> s = <span class="hljs-string" style="color: rgb(221, 17, 68);">"Hello, World!"</span>
<span class="hljs-keyword" style="font-weight: bold;">let</span> i = s.index(<span class="hljs-keyword" style="font-weight: bold;">where</span>: <span class="hljs-string" style="color: rgb(221, 17, 68);">","</span>)
<span class="hljs-keyword" style="font-weight: bold;">let</span> greeting = s[s.startIndex..&lt;i]</code></pre><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">When performing lots of slicing like this, the verbosity of repeating&nbsp;<code style="line-height: 1;" class="">s.startIndex</code>&nbsp;is tiresome to write and harmful to readability.</p><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">Swift 3’s solution to this is a family of methods:</p><pre style="margin-top: 21px; margin-bottom: 21px; tab-size: 4; color: rgb(17, 17, 17); font-size: 11.999999046325684px; height: 60px; background-color: rgb(248, 248, 248);" class=""><code class="swift hljs" style="line-height: inherit; display: block; overflow-x: auto; padding: 0.5em; color: rgb(51, 51, 51); height: auto;"><span class="hljs-keyword" style="font-weight: bold;">let</span> greeting = s.<span class="hljs-keyword" style="font-weight: bold;">prefix</span>(upTo: i)
<span class="hljs-keyword" style="font-weight: bold;">let</span> withComma = s.<span class="hljs-keyword" style="font-weight: bold;">prefix</span>(through: i)
<span class="hljs-keyword" style="font-weight: bold;">let</span> location = s.suffix(from: i)</code></pre><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">The two very different-looking ways to perform a similar task is jarring. And as methods, the result cannot be used as an l-value.</p><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">A variant of the one-sided slicing syntax found in Python (i.e.&nbsp;<code style="line-height: 1;" class="">s[i:]</code>) is proposed to resolve this.</p><h2 id="proposed-solution" style="color: rgb(17, 17, 17); font-size: 27px; line-height: 42px; margin-top: 42px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;" class="">Proposed solution</h2><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">Introduce a one-sided range syntax, where the “missing” side is inferred to be the start/end:</p><pre style="margin-top: 21px; margin-bottom: 21px; tab-size: 4; color: rgb(17, 17, 17); font-size: 11.999999046325684px; height: 108px; background-color: rgb(248, 248, 248);" class=""><code class="swift hljs" style="line-height: inherit; display: block; overflow-x: auto; padding: 0.5em; color: rgb(51, 51, 51); height: auto;"><span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// half-open right-handed range</span>
<span class="hljs-keyword" style="font-weight: bold;">let</span> greeting = s[..&lt;i]
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// closed right-handed range</span>
<span class="hljs-keyword" style="font-weight: bold;">let</span> withComma = s[...i]
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// left-handed range (no need for half-open variant)</span>
<span class="hljs-keyword" style="font-weight: bold;">let</span> location = s[i...]</code></pre><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">Additionally, when the index is a countable type,&nbsp;<code style="line-height: 1;" class="">i...</code>&nbsp;should form a&nbsp;<code style="line-height: 1;" class="">Sequence</code>&nbsp;that counts up from&nbsp;<code style="line-height: 1;" class="">i</code>&nbsp;indefinitely. This is useful in forming variants of&nbsp;<code style="line-height: 1;" class="">Sequence.enumerated()</code>&nbsp;when you either want them non-zero-based i.e.&nbsp;<code style="line-height: 1;" class="">zip(1..., greeting)</code>, or want to flip the order i.e.&nbsp;<code style="line-height: 1;" class="">zip(greeting, 0...)</code>.</p><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">This syntax would supercede the existing&nbsp;<code style="line-height: 1;" class="">prefix</code>&nbsp;and&nbsp;<code style="line-height: 1;" class="">suffix</code>&nbsp;operations that take indices, which will be deprecated in a later release. Note that the versions that take distances are not covered by this proposal, and would remain.</p><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">This will require the introduction of new range types (e.g.&nbsp;<code style="line-height: 1;" class="">PartialRangeThrough</code>). There are already multiple range types (e.g.&nbsp;<code style="line-height: 1;" class="">ClosedRange</code>,&nbsp;<code style="line-height: 1;" class="">CountableHalfOpenRange</code>), which require overloads to allow them to be used whereever a&nbsp;<code style="line-height: 1;" class="">Range</code>&nbsp;can be.</p><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">To unify these different range types, a new protocol,&nbsp;<code style="line-height: 1;" class="">RangeExpression</code>&nbsp;will be created and all ranges conformed to it. Existing overloads taking concrete types other than&nbsp;<code style="line-height: 1;" class="">Range</code>&nbsp;can then be replaced with a single generic method that takes a&nbsp;<code style="line-height: 1;" class="">RangeExpression</code>, converts it to a&nbsp;<code style="line-height: 1;" class="">Range</code>, and then forward the method on.</p><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">A generic version of&nbsp;<code style="line-height: 1;" class="">~=</code>&nbsp;will also be implemented for all range expressions:</p><pre style="margin-top: 21px; margin-bottom: 21px; tab-size: 4; color: rgb(17, 17, 17); font-size: 11.999999046325684px; height: 76px; background-color: rgb(248, 248, 248);" class=""><code class="swift hljs" style="line-height: inherit; display: block; overflow-x: auto; padding: 0.5em; color: rgb(51, 51, 51); height: auto;"><span class="hljs-keyword" style="font-weight: bold;">switch</span> i {
<span class="hljs-keyword" style="font-weight: bold;">case</span> <span class="hljs-number" style="color: rgb(0, 128, 128);">9001</span>...: <span class="hljs-built_in" style="color: rgb(0, 134, 179);">print</span>(<span class="hljs-string" style="color: rgb(221, 17, 68);">"It’s over NINE THOUSAAAAAAAND"</span>)
<span class="hljs-keyword" style="font-weight: bold;">default</span>: <span class="hljs-built_in" style="color: rgb(0, 134, 179);">print</span>(<span class="hljs-string" style="color: rgb(221, 17, 68);">"There's no way that can be right!"</span>)
}</code></pre><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">The existing concrete overloads that take ranges other than&nbsp;<code style="line-height: 1;" class="">Range</code>&nbsp;will be deprecated in favor of generic ones that take a&nbsp;<code style="line-height: 1;" class="">RangeExpression</code>.</p><h2 id="detailed-design" style="color: rgb(17, 17, 17); font-size: 27px; line-height: 42px; margin-top: 42px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;" class="">Detailed design</h2><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">Add the following to the standard library:</p><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">(a fuller work-in-progress implementation can be found here:&nbsp;<a href="https://github.com/apple/swift/pull/8710" style="color: rgb(13, 110, 161); text-decoration: none; transition: color 0.2s ease-in-out;" class="">https://github.com/apple/swift/pull/8710</a>)</p><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">NOTE: The following is subject to change depending on pending compiler features. Methods may actually be on&nbsp;<ins id="firstdiff" style="display: inline-block; position: absolute; left: -8px; text-decoration: none !important; border: none !important; background-image: none !important; background-position: initial initial !important; background-repeat: initial initial !important;" class=""></ins>underscored protocols, and then moved once recursive protocols are implemented. Types may be collapsed using conditional conformance. This should not matter from a usage perspective – users are not expected to use these types directly or override any of the behaviors in their own types. Any final implementation will follow the below in spirit if not in practice.</p><pre style="margin-top: 21px; margin-bottom: 21px; tab-size: 4; color: rgb(17, 17, 17); font-size: 11.999999046325684px; height: 1180px; background-color: rgb(248, 248, 248);" class=""><code class="swift hljs" style="line-height: inherit; display: block; overflow-x: auto; padding: 0.5em; color: rgb(51, 51, 51); height: auto;"><span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="font-weight: bold;">protocol</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">RangeExpression</span> </span>{
    associatedtype <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Bound</span>: <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Comparable</span>

    <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">/// Returns `self` expressed as a range of indices within `collection`.</span>
    <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">///</span>
    <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">/// -Parameter collection: The collection `self` should be</span>
    <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">///                        relative to.</span>
    <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">///</span>
    <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">/// -Returns: A `Range&lt;Bound&gt;` suitable for slicing `collection`.</span>
    <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">///           The return value is *not* guaranteed to be inside</span>
    <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">///           its bounds. Callers should apply the same preconditions</span>
    <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">///           to the return value as they would to a range provided</span>
    <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">///           directly by the user.</span>
    <span class="hljs-function"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">relative</span>&lt;C: _Indexable&gt;<span class="hljs-params">(to collection: C)</span></span> -&gt; <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Range</span>&lt;<span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Bound</span>&gt; <span class="hljs-keyword" style="font-weight: bold;">where</span> <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">C</span>.<span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Index</span> == <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Bound</span>

    <span class="hljs-function"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">contains</span><span class="hljs-params">(<span class="hljs-number" style="color: rgb(0, 128, 128);">_</span> element: Bound)</span></span> -&gt; <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Bool</span>
}

<span class="hljs-class"><span class="hljs-keyword" style="font-weight: bold;">extension</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">RangeExpression</span> </span>{
  <span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">static</span> <span class="hljs-function"><span class="hljs-keyword" style="font-weight: bold;">func</span> ~= <span class="hljs-params">(pattern: <span class="hljs-keyword" style="font-weight: bold;">Self</span>, value: Bound)</span></span> -&gt; <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Bool</span>
}

<span class="hljs-keyword" style="font-weight: bold;">prefix</span> <span class="hljs-keyword" style="font-weight: bold;">operator</span> ..&lt;
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="font-weight: bold;">struct</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">PartialRangeUpTo</span>&lt;<span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">T</span>: <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">Comparable</span>&gt;: <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">RangeExpression</span> </span>{
  <span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">init</span>(<span class="hljs-number" style="color: rgb(0, 128, 128);">_</span> upperBound: <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">T</span>) { <span class="hljs-keyword" style="font-weight: bold;">self</span>.upperBound = upperBound }
  <span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">let</span> upperBound: <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">T</span>
}
<span class="hljs-class"><span class="hljs-keyword" style="font-weight: bold;">extension</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">Comparable</span> </span>{
  <span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">static</span> <span class="hljs-keyword" style="font-weight: bold;">prefix</span> <span class="hljs-function"><span class="hljs-keyword" style="font-weight: bold;">func</span> ..&lt;(x: Self) -&gt; <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">PartialRangeUpTo</span>&lt;Self&gt;
}

<span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">prefix</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">operator</span> ...
<span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">public</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">struct</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">PartialRangeThrough</span>&lt;T: Comparable&gt;: <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">RangeExpression</span> </span>{
  <span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">init</span>(<span class="hljs-number" style="color: rgb(0, 128, 128);">_</span> upperBound: <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">T</span>)
  <span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">let</span> upperBound: <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">T</span>
}
<span class="hljs-class"><span class="hljs-keyword" style="font-weight: bold;">extension</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">Comparable</span> </span>{
  <span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">static</span> <span class="hljs-keyword" style="font-weight: bold;">prefix</span> <span class="hljs-function"><span class="hljs-keyword" style="font-weight: bold;">func</span> ...<span class="hljs-params">(x: <span class="hljs-keyword" style="font-weight: bold;">Self</span>)</span></span> -&gt; <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">PartialRangeThrough</span>&lt;<span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Self</span>&gt;
}

<span class="hljs-keyword" style="font-weight: bold;">postfix</span> <span class="hljs-keyword" style="font-weight: bold;">operator</span> ...
<span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="font-weight: bold;">struct</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">PartialRangeFrom</span>&lt;<span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">T</span>: <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">Comparable</span>&gt;: <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">RangeExpression</span> </span>{
  <span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">init</span>(<span class="hljs-number" style="color: rgb(0, 128, 128);">_</span> lowerBound: <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">T</span>)
  <span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">let</span> lowerBound: <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">T</span>
}
<span class="hljs-class"><span class="hljs-keyword" style="font-weight: bold;">extension</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">Comparable</span> </span>{
  <span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">static</span> <span class="hljs-keyword" style="font-weight: bold;">postfix</span> <span class="hljs-function"><span class="hljs-keyword" style="font-weight: bold;">func</span> ...<span class="hljs-params">(x: <span class="hljs-keyword" style="font-weight: bold;">Self</span>)</span></span> -&gt; <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">PartialRangeFrom</span>&lt;<span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Self</span>&gt;
}

<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// The below relies on Conditional Conformance. Pending that feature,</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// this may require an additional CountablePartialRangeFrom type temporarily.</span>
<span class="hljs-class"><span class="hljs-keyword" style="font-weight: bold;">extension</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">PartialRangeFrom</span>: <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">Sequence</span> 
  <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">where</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">Index</span>: <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">_Strideable</span>, <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">Index</span>.<span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">Stride</span> : <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">SignedInteger</span>


<span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">extension</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">Collection</span> </span>{
  <span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">subscript</span>&lt;<span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">R</span>: <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">RangeExpression</span>&gt;(r: <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">R</span>) -&gt; <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">SubSequence</span>
   <span class="hljs-keyword" style="font-weight: bold;">where</span> <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">R</span>.<span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Bound</span> == <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Index</span> { <span class="hljs-keyword" style="font-weight: bold;">get</span> }
}
<span class="hljs-class"><span class="hljs-keyword" style="font-weight: bold;">extension</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">MutableCollection</span> </span>{
  <span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">subscript</span>&lt;<span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">R</span>: <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">RangeExpression</span>&gt;(r: <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">R</span>) -&gt; <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">SubSequence</span>
   <span class="hljs-keyword" style="font-weight: bold;">where</span> <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">R</span>.<span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Bound</span> == <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Index</span> { <span class="hljs-keyword" style="font-weight: bold;">get</span> <span class="hljs-keyword" style="font-weight: bold;">set</span> }
}
  
<span class="hljs-class"><span class="hljs-keyword" style="font-weight: bold;">extension</span> <span class="hljs-title" style="color: rgb(68, 85, 136); font-weight: bold;">RangeReplaceableColleciton</span> </span>{
  <span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">mutating</span> <span class="hljs-function"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">replaceSubrange</span>&lt;C: Collection, R: RangeExpression&gt;<span class="hljs-params">(
    <span class="hljs-number" style="color: rgb(0, 128, 128);">_</span> subrange: ${Range}&lt;Index&gt;, with newElements: C
  )</span></span> <span class="hljs-keyword" style="font-weight: bold;">where</span> <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">C</span>.<span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Iterator</span>.<span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Element</span> == <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Iterator</span>.<span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Element</span>, <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">R</span>.<span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Bound</span> == <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Index</span>

  <span class="hljs-keyword" style="font-weight: bold;">public</span> <span class="hljs-keyword" style="font-weight: bold;">mutating</span> <span class="hljs-function"><span class="hljs-keyword" style="font-weight: bold;">func</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">removeSubrange</span>&lt;R: RangeExpression&gt;<span class="hljs-params">(
    <span class="hljs-number" style="color: rgb(0, 128, 128);">_</span> subrange: ${Range}&lt;Index&gt;
  )</span></span> <span class="hljs-keyword" style="font-weight: bold;">where</span> <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">R</span>.<span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Bound</span> == <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Index</span>
}</code></pre><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">Additionally, these new ranges will implement appropriate protocols such as&nbsp;<code style="line-height: 1;" class="">CustomStringConvertible</code>.</p><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">It is important to note that these new methods and range types are&nbsp;<em style="line-height: 1;" class="">extensions only</em>. They are not protocol requirements, as they should not need to be customized for specific collections. They exist only as shorthand to expand out to the full slicing operation.</p><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">The&nbsp;<code style="line-height: 1;" class="">prefix</code>&nbsp;and&nbsp;<code style="line-height: 1;" class="">suffix</code>&nbsp;methods that take an index&nbsp;<em style="line-height: 1;" class="">are</em>&nbsp;currently protocol requirements, but should not be. This proposal will fix that as a side-effect.</p><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">Where&nbsp;<code style="line-height: 1;" class="">PartialRangeFrom</code>&nbsp;is a&nbsp;<code style="line-height: 1;" class="">Sequence</code>, it is left up to the type of&nbsp;<code style="line-height: 1;" class="">Index</code>&nbsp;to control the behavior when the type is incremented past its bounds. In the case of an&nbsp;<code style="line-height: 1;" class="">Int</code>, the iterator will trap when iterating past&nbsp;<code style="line-height: 1;" class="">Int.max</code>. Other types, such as a&nbsp;<code style="line-height: 1;" class="">BigInt</code>&nbsp;that could be incremented indefinitely, would behave differently.</p><h2 id="source-compatibility" style="color: rgb(17, 17, 17); font-size: 27px; line-height: 42px; margin-top: 42px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;" class="">Source compatibility</h2><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">The new operators/types are purely additive so have no source compatibility consequences. Replacing the overloads taking concrete ranges other than&nbsp;<code style="line-height: 1;" class="">Range</code>&nbsp;with a single generic version is source compatible.&nbsp;<code style="line-height: 1;" class="">prefix</code>&nbsp;and&nbsp;<code style="line-height: 1;" class="">suffix</code>&nbsp;will be deprecated in Swift 4 and later removed.</p><h2 id="effect-on-abi-stability" style="color: rgb(17, 17, 17); font-size: 27px; line-height: 42px; margin-top: 42px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;" class="">Effect on ABI stability</h2><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">The&nbsp;<code style="line-height: 1;" class="">prefix</code>/<code style="line-height: 1;" class="">suffix</code>&nbsp;methods being deprecated should be eliminated before declaring ABI stability.</p><h2 id="effect-on-api-resilience" style="color: rgb(17, 17, 17); font-size: 27px; line-height: 42px; margin-top: 42px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;" class="">Effect on API resilience</h2><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">The new operators/types are purely additive so have no resilience consequences.</p><h2 id="alternatives-considered" style="color: rgb(17, 17, 17); font-size: 27px; line-height: 42px; margin-top: 42px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;" class="">Alternatives considered</h2><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class=""><code style="line-height: 1;" class="">i...</code>&nbsp;is favored over&nbsp;<code style="line-height: 1;" class="">i..&lt;</code>&nbsp;because the latter is ugly. We have to pick one, two would be redundant and likely to cause confusion over which is the “right” one. Either would be reasonable on pedantic correctness grounds –&nbsp;<code style="line-height: 1;" class="">(i as Int)...</code>&nbsp;includes&nbsp;<code style="line-height: 1;" class="">Int.max</code>&nbsp;consistent with&nbsp;<code style="line-height: 1;" class="">...</code>, whereas&nbsp;<code style="line-height: 1;" class="">a[i...]</code>&nbsp;is interpreted as&nbsp;<code style="line-height: 1;" class="">a[i..&lt;a.endIndex]</code>&nbsp;consistent with&nbsp;<code style="line-height: 1;" class="">i..&lt;</code>.</p><p style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;" class="">It might be nice to consider extend this domain-specific language inside the subscript in other ways. For example, to be able to incorporate the index distance versions of prefix, or add distance offsets to the indices used within the subscript. This proposal explicitly avoids proposals in this area. Such ideas would be considerably more complex to implement, and would make a good project for investigation by an interested community member, but would not fit within the timeline for Swift 4.</p></div></div>_______________________________________________<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=""></div></blockquote></div><br class=""></body></html>