[swift-evolution] Strings in Swift 4

Jonathan Hull jhull at gbis.com
Sat Feb 4 02:57:28 CST 2017


> On Feb 2, 2017, at 2:19 PM, Dave Abrahams <dabrahams at apple.com> wrote:
> 
> 
> on Thu Feb 02 2017, Jonathan Hull <jhull-AT-gbis.com> wrote:
> 
>> Just out of curiosity, what are the use-cases for an infinite sequence
>> (as opposed to a sequence which is bounded to the type’s representable
>> values)?
> 
> 1. The type may not have an inherent expressible bound (see BigInt,
>   UnsafePointer, and *many* real-life Index types).

If I understand what you are saying, this is why I was arguing that these partial ranges should not, by themselves, conform to Sequence.  In cases where you do have a natural expressible bound, then it should conditionally conform to sequence.  In other cases, you should have to write that conformance yourself if you want it.


> 
> 2. I keep repeating variants of this example:
> 
>  func listElements<
>    S: Sequence, N: Number
>> (of s: S, numberedFrom start: N) {
>    for (n, e) in zip(start..., s) {
>      print("\(n). \(e)")
>    }
>  }
> 
>  which avoids incorrect behavior when N turns out to be a type that
>  can't represent values high enough to list everything in s—**if and
>  only if** `start...` is an unbounded range, rather than one that
>  implicitly gets its upper bound from its type.

I really worry about the possibility of long-term foot-gunning in this case.  I showed this to a friend who maintains old/abandoned codebases for a living, and he said “Oh god, that isn’t going to actually crash until 5 years in, when it gets passed some rare type of file… and by then the original programmer will have left.”  He hit on exactly what I had been feeling as well (but hadn’t been able to put into words until I heard his).  The thought is that this will help the programmer find an error by trapping, but because it is dependent on the interactions of two subsystems, it will often create one of those crashes where the stars have to align for it to happen (which are my least favorite type of bug/crash to debug).


I think this example also shows how my suggestion of requiring an extra protocol for conformance to Sequence would actually be much more effective in preventing the programmer error…

You would not have been able to write the function the way you did, because writing ‘start…’ as a sequence would have required the addition of ‘where N:FiniteComparable’ (or whatever we call the protocol providing natural bounds).  In having to write that N needs bounds, you are much more likely to be thinking of what those bounds might be.  The problem here is really with the design of the listElements function in allowing/encouraging that error, as opposed to the caller... and the trap is more likely to make you look at the call site because of the context of when it happens. Having to write the ‘where’ statement makes you reconsider the design of the function, again because of the context of when it happens.

Thanks,
Jon










More information about the swift-evolution mailing list