Strings in Swift 4


(James Froggatt) #1

Going to try resending this - my client doesn't seem to give me a proper email address to reply to (only some gmane mangled address which got me a delivery failure); sorry for the lack of a direct reply.

···

---

Exactly. I'm not too familiar with range subscripting on arrays, but if it's anything like a regular Int subscript, I'd expect…

let outOfBoundsSubrange = items[items.startIndex...items.endIndex]

…to give an out of bounds error, since (in my mental model) it tries to access items[items.endIndex].

If ‘items.startIndex...’ represents an unbounded range (one with a unknown / subscript-defined endIndex), I can't see enough use-cases for it outside of subscripting to justify its existence as a type - it can't even conform to sequence, since there is no endIndex, making it essentially just a number and a promise of how APIs will use it. If we pretend an unbounded range is infinite by conforming it to sequence, people will inevitably use it like one.

If this syntax represents an infinite range, I'd expect it to similarly give an error when used to subscript a non-infinite array-like type, but it would at least be independently useful outside of collections as a way to generate an infinite sequence.

As a further point, what if we also implemented prefix comparison operators? Which of the following looks more like an infinite range, and which looks more like an unbounded one? I'll leave the answer up to the reader:

let indices = >oneDigitNums.startIndex
oneDigitNums[>5]

let indices = oneDigitNums.startIndex...
oneDigitNums[5...]

------------ Begin Message ------------
Group: gmane.comp.lang.swift.evolution
MsgID: <CD036AEB-35F5-41C9-8E7F-C223EDC6A3A5@gmail.com>

On Jan 30, 2017, at 11:35 AM, Dave Abrahams via swift-evolution <swift-evolution-m3FHrko0VLzYtjvyW6yDsg@public.gmane.org> wrote:

Why should that be out-of-bounds? Whether it is out-of-bounds would
depend on what items is. If it's an array, that should be equivalent to

let x = items[items.startIndex..<items.endIndex]

It seems to me that `items[0…]` would be equivalent to `items[0…Int.max]` if we’re going to treat `0…` as an “infinite" range, no? Otherwise, we’re either giving subscript of InfiniteRange types special behavior or we’re making subscript ignore past-the-end indices; `”hello”.characters[0…10]` would need to return the same as “hello”.characters[0…4]` to be consistent.

------------- End Message -------------

From James


(James Froggatt) #2

While an unbounded range doesn't need an endIndex to conform to Sequence, conformance would let you iterate over it.

If someone were to iterate over it, and, for example, get the numbers [5, 6, 7, 8], one could take that to mean that those numbers are part of the sequence. Based on this, users could:
1. Be tempted to use it as an infinite range (as opposed to unbounded).
2. Be confused when the 7 and 8 which were just confirmed to be in the sequence are ignored when subscripting.

To put it another way, it would be reasonable to expect the following to be equivalent (or fail equivalently):

let x = array[sequenceOfIndices]
let y = sequenceOfIndices.map{array[$0]}

The idea that it is infinite when used in one way but finite when used in another seems very wrong.

From James

···

On 31 Jan 2017, at 07:00, David Hart <david@hartbit.com> wrote:

Sent from my iPhone

On 31 Jan 2017, at 02:04, James Froggatt via swift-evolution <swift-evolution@swift.org> wrote:

Going to try resending this - my client doesn't seem to give me a proper email address to reply to (only some gmane mangled address which got me a delivery failure); sorry for the lack of a direct reply.

---

Exactly. I'm not too familiar with range subscripting on arrays, but if it's anything like a regular Int subscript, I'd expect…

let outOfBoundsSubrange = items[items.startIndex...items.endIndex]

…to give an out of bounds error, since (in my mental model) it tries to access items[items.endIndex].

Like you say below, i... doesn't have an endIndex, so it doesn't make sense to represent it as items.startIndex...items.endIndex. It's open unbounded range. So it doesn't break my mental model :slight_smile:

If ‘items.startIndex...’ represents an unbounded range (one with a unknown / subscript-defined endIndex), I can't see enough use-cases for it outside of subscripting to justify its existence as a type - it can't even conform to sequence, since there is no endIndex, making it essentially just a number and a promise of how APIs will use it. If we pretend an unbounded range is infinite by conforming it to sequence, people will inevitably use it like one.

Sequence does not require an endIndex. Collection does. So, as Dave shown, it can actually be very useful: see how he redefined enumerated using the unbounded range and zip? That's really cool! How about using it to make for loops act as a infinite while loop with an index?

var index = 0
while true {
  // break somewhere here
}

Becomes:

for index in 0... {
}

If this syntax represents an infinite range, I'd expect it to similarly give an error when used to subscript a non-infinite array-like type, but it would at least be independently useful outside of collections as a way to generate an infinite sequence.

As a further point, what if we also implemented prefix comparison operators? Which of the following looks more like an infinite range, and which looks more like an unbounded one? I'll leave the answer up to the reader:

let indices = >oneDigitNums.startIndex
oneDigitNums[>5]

let indices = oneDigitNums.startIndex...
oneDigitNums[5...]

I prefer the latter :slight_smile: At least it uses a Range operator.

------------ Begin Message ------------
Group: gmane.comp.lang.swift.evolution
MsgID: <CD036AEB-35F5-41C9-8E7F-C223EDC6A3A5@gmail.com>

On Jan 30, 2017, at 11:35 AM, Dave Abrahams via swift-evolution <swift-evolution-m3FHrko0VLzYtjvyW6yDsg@public.gmane.org> wrote:

Why should that be out-of-bounds? Whether it is out-of-bounds would
depend on what items is. If it's an array, that should be equivalent to

let x = items[items.startIndex..<items.endIndex]

It seems to me that `items[0…]` would be equivalent to `items[0…Int.max]` if we’re going to treat `0…` as an “infinite" range, no? Otherwise, we’re either giving subscript of InfiniteRange types special behavior or we’re making subscript ignore past-the-end indices; `”hello”.characters[0…10]` would need to return the same as “hello”.characters[0…4]` to be consistent.

------------- End Message -------------

From James
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Thorsten Seitz) #3

If I understand correctly, `1...` is not a Range but a RangeExpression which should not conform to Sequence and would need to be provided with a value for its open end to turn it into a Range.

Subscript would provide the last valid index in your first example and for your second example you would have to provide the desired end yourself.

Just voicing my exceptions for the different types as I cannot currently check their implementation.

-Thorsten

···

Am 31.01.2017 um 12:36 schrieb James Froggatt via swift-evolution <swift-evolution@swift.org>:

While an unbounded range doesn't need an endIndex to conform to Sequence, conformance would let you iterate over it.

If someone were to iterate over it, and, for example, get the numbers [5, 6, 7, 8], one could take that to mean that those numbers are part of the sequence. Based on this, users could:
1. Be tempted to use it as an infinite range (as opposed to unbounded).
2. Be confused when the 7 and 8 which were just confirmed to be in the sequence are ignored when subscripting.

To put it another way, it would be reasonable to expect the following to be equivalent (or fail equivalently):

let x = array[sequenceOfIndices]
let y = sequenceOfIndices.map{array[$0]}

The idea that it is infinite when used in one way but finite when used in another seems very wrong.

From James

On 31 Jan 2017, at 07:00, David Hart <david@hartbit.com> wrote:

Sent from my iPhone

On 31 Jan 2017, at 02:04, James Froggatt via swift-evolution <swift-evolution@swift.org> wrote:

Going to try resending this - my client doesn't seem to give me a proper email address to reply to (only some gmane mangled address which got me a delivery failure); sorry for the lack of a direct reply.

---

Exactly. I'm not too familiar with range subscripting on arrays, but if it's anything like a regular Int subscript, I'd expect…

let outOfBoundsSubrange = items[items.startIndex...items.endIndex]

…to give an out of bounds error, since (in my mental model) it tries to access items[items.endIndex].

Like you say below, i... doesn't have an endIndex, so it doesn't make sense to represent it as items.startIndex...items.endIndex. It's open unbounded range. So it doesn't break my mental model :slight_smile:

If ‘items.startIndex...’ represents an unbounded range (one with a unknown / subscript-defined endIndex), I can't see enough use-cases for it outside of subscripting to justify its existence as a type - it can't even conform to sequence, since there is no endIndex, making it essentially just a number and a promise of how APIs will use it. If we pretend an unbounded range is infinite by conforming it to sequence, people will inevitably use it like one.

Sequence does not require an endIndex. Collection does. So, as Dave shown, it can actually be very useful: see how he redefined enumerated using the unbounded range and zip? That's really cool! How about using it to make for loops act as a infinite while loop with an index?

var index = 0
while true {
// break somewhere here
}

Becomes:

for index in 0... {
}

If this syntax represents an infinite range, I'd expect it to similarly give an error when used to subscript a non-infinite array-like type, but it would at least be independently useful outside of collections as a way to generate an infinite sequence.

As a further point, what if we also implemented prefix comparison operators? Which of the following looks more like an infinite range, and which looks more like an unbounded one? I'll leave the answer up to the reader:

let indices = >oneDigitNums.startIndex
oneDigitNums[>5]

let indices = oneDigitNums.startIndex...
oneDigitNums[5...]

I prefer the latter :slight_smile: At least it uses a Range operator.

------------ Begin Message ------------
Group: gmane.comp.lang.swift.evolution
MsgID: <CD036AEB-35F5-41C9-8E7F-C223EDC6A3A5@gmail.com>

On Jan 30, 2017, at 11:35 AM, Dave Abrahams via swift-evolution <swift-evolution-m3FHrko0VLzYtjvyW6yDsg@public.gmane.org> wrote:

Why should that be out-of-bounds? Whether it is out-of-bounds would
depend on what items is. If it's an array, that should be equivalent to

let x = items[items.startIndex..<items.endIndex]

It seems to me that `items[0…]` would be equivalent to `items[0…Int.max]` if we’re going to treat `0…` as an “infinite" range, no? Otherwise, we’re either giving subscript of InfiniteRange types special behavior or we’re making subscript ignore past-the-end indices; `”hello”.characters[0…10]` would need to return the same as “hello”.characters[0…4]` to be consistent.

------------- End Message -------------

From James
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution