Swift 4 之单边区间 One-Sided Range

675 阅读1分钟

单区间做了增强,能够自动推断左右边界。

let esports = ["Hearthstone", "CS:GO", "League of Legends", "Super Smash Bros", "Overwatch", "Gigantic"]

esports[3...] 
// returns ["Super Smash Bros", "Overwatch", "Gigantic"]

// In Swift 3, you had to write 
esports[3..<esports.endIndex]

esports[...2] 
// returns ["Hearthstone", "CS:GO", "League of Legends"]

esports[..<2] 
// returns ["Hearthstone", "CS:GO"]

表达无穷序列

单边区间可以被认为是无穷大的区间,主要是利用 range 的可推断性,当需要使用 range 更远的元素时,能够自动去创建。

eg:

let uppercase = ["A", "B", "C", "D"] 

// zip 操作符在处理的过程中,需要 range 进行不断增大,那么就会按照 RangeExpression 协议去访问 Range 中的元素。
let asciiCodes = zip(65..., uppercase) 
print(Array(asciiCodes)) 

// prints [(65, "A"), (66, "B"), (67, "C"), (68, "D")]

这些都主要是利用了 Swift 中最新的 RangeExpression 协议。

在 swift 3 中,也是可以实现上述需求的。

let s = "Hello, World!"
let i = s.index(of: ",")!

// 使用 range 获取 subString
let greeting = s[s.startIndex..<i] 

// 对集合进行切片
let greeting = s.prefix(upTo: i) // Hello
let withComma = s.prefix(through: i) // Hello
let location = s.suffix(from: i)

但是无论怎么看,Swift 4 的实现都要更加简洁易读,而且不容易出错。

模式匹配

range 在 swift 4 之前也是可以用在 pattern match 上的。 不过比较局限,需要使用 Int 等基础类型。

在 swift 4 中,还可以使用 Double 这种类型。

eg:

/// 模式匹配可以用在 double 这种无限细粒度划分的类型中。
func sentiment(_ rating: Double) -> String {
    switch rating { 
    case ..<0.33:
        return "A" 
    case ..<0.66:
        return "B" 
    default:
        return "C"
    }
}

sentiment(0.5)

// returns B

RangeExpression

刚才已经看了 Range 在使用上的优势,那么 swift 4 中是如何实现的呢?

关于Range 新特性的讨论可以看这里: RangeExpression-Evolution