Swift Substring

let s = "one two three"
 let r = advance(s.startIndex, 4)..<advance(s.endIndex, -6)
let substring = s[r]

I wish I could talk to who ever created this syntax. Why in the world a simple substring operation has to be this complicated! People have to do some serious search to find out how to do it!

Suggestion:

1. Make it simpler such as s[start..end]

2. If you believe what you designed is the best, then make better auto completion in XCode!

Strings in Swift 2.0 intentionally don't conform to the ColectionType protocol. You'll need to use one of the various views on a string of you want to index into it easily. Two reasons for this: (a) to remind you that this isn't an O(1) operation (at least not for the characters view) and (b) to make you think about which view you need to use for whatever you're trying to do. See the recent post on the Swift Blog.

NSString's substringWithRange: should work fine.

NSString's substringWithRange: should work fine.

That depends on what you mean by fine. Yes, it'll work fine if the string only contains characters encodable as ASCII. For anything more complex than that, even for something as simple as Latin-1,

-substringWithRange:
makes it easy to fall into some common pitfalls. The most common of these are:
  • you might erroneously split a surrogate pair

  • you might accidentally split a character from its combining accents

  • you might erroneously assume that, for two strings to be equal, they must have the same length

The Swift string API is designed to deal with the complexities of non-ASCII string processing. The cost of that design is that you lose the ability to treat strings like ASCII if you know they really are ASCII (for example, if you're dealing with strings in a network protocol).

Which brings us back to the original question. The example only makes sense if you can guarantee that

s
is an ASCII string. So, @Shuhao, are you asking about how to deal nicely with ASCII strings? Or about dealing with strings that are user visible?

IMPORTANT I've used the term ASCII deliberately here because some of the assumptions I've described above don't hold for English. Assuming that ASCII is sufficient to represent English would be naïve. For example:

import Foundation

let s1 = "na\u{ef}ve"
let s2 = "nai\u{0308}ve"
println(s1)                 // prints "naïve"
println(s2)                 // prints "naïve"
println(s1 == s2)           // prints "true"
println(s1.dataUsingEncoding(NSUTF8StringEncoding) == s2.dataUsingEncoding(NSUTF8StringEncoding)) // prints "false"

Share and Enjoy

Quinn "The Eskimo!"
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I just posted a similar question to this only to see this thread in the "more like this"-section. Anyway, I've proposed a less cumbersome alternative for dealing with substrings in there.

It would be interesting to hear the reasons for why something similar to that can/should not be part of the std lib.

Swift Substring
 
 
Q