美文网首页
更方便的单边Range

更方便的单边Range

作者: 醉看红尘这场梦 | 来源:发表于2020-03-18 10:58 被阅读0次

    安装Swift Toolchain

    在开始这个系列的内容之前,你需要先安装Swift 4对应的toolchain。这很简单,在swift.org上下载Swift 4分支的镜像:

    se-0172

    下载安装完之后,打开Xcode,按Cmd + ,打开属性设置,在Components -> Toolchain中,选择Swift 4.0 Snapshot,这样就可以在Xcode中体验Swift 4的各种特性了。

    如果你希望在命令行中使用Swift 4 toolchain中的工具,把下面这行命令根据使用的终端添加到~/.bashrc~/.zshrc中:

    $ export PATH=/Library/Developer/Toolchains/swift-latest.xctoolchain/usr/bin:"${PATH}"
    
    

    重新打开终端,执行下面的命令:

    swift --version
    swift package --version
    
    
    se-0172

    如果可以看到类似4.0-dev的信息,就表示命令行工具已经安装完成。至此,我们已经准备就绪,可以体验Swift 4的各种新特性了。

    SE-0172

    更方便的截取集合切片

    之前,当我们要在一个集合中从开始截断到某个位置,或从某个位置截取到末尾,只能这样:

    let s = "Hello Mars"
    var i = s.index(of: " ")!
    let greeting = s[s.startIndex ..< i] // Hello
    
    i = s.index(i, offsetBy: 1)
    let name = s[i..<s.endIndex] // Mars
    
    

    这看似没问题,当我们要频繁的对集合进行切片的时候,大量编写s.startIndexs.endIndex就会显得很啰嗦。

    为此,在Swift3中,提供了下面这样的API,可以部分简化上面的工作:

    // In Swift 3
    let greeting = s.prefix(upTo: i) // Hello
    let greetingWithSpace = s.prefix(through: i) // "Hello "
    
    i = s.index(i, offsetBy: 1)
    let name = s.suffix(from: i) // Mars
    
    

    尽管prefixsuffix的表意更明确,但添加了API之后也并不那么尽善尽美。一来,为了完成相同的任务,现在我们有了两个不同的选择;二来,调用API写起来仍旧很麻烦。所以,也许我们需要的,并不是更多的API,而是对Range操作符的进一步增强。

    于是,基于Swift 3更新的三个API,Swift 4中添加了三种不同的Range操作符,之前的代码就可以写成这样:

    let greeting = s[..<i] // Hello
    let greetingWithSpace = s[...i] // "Hello "
    
    i = s.index(i, offsetBy: 1)
    let name = s[i...] // Mars
    
    

    在上面的例子中可以看到:

    • ..<i,对应s.prefix(upTo:),表达从集合开始到i的半闭半开区间;
    • ...i,对应s.prefix(through:),表达从集合开始到i的闭区间;
    • i...,对应s.suffix(from: i),表达从i开始到集合结束的半闭半开区间,由于集合的endIndex位置并不能读取,因此这里没有没有所谓的.....<的差别了,而之所以选择了i...而不是i..<,仅仅是因为前者看上去更好看一些罢了,尽管,它表达的含义的确是i..<

    更方便的表达无穷序列

    除了用在集合的下标操作符中,i...这样的形式还可以生成一个包含无穷个元素的Sequence,因此,对于enumerated()的结果:

    Array(s.enumerated())
    // [(0, "H"), (1, "e"), (2, "l"), ...]
    
    

    如果你不希望列举出来的结果从0开始,就可以这样:

    Array(zip(1..., s))
    // [(1, "H"), (2, "e"), (3, "l"), ...]
    
    

    或者,如果想把字符放在前面,还可以这样:

    Array(zip(s, 1...))
    // [("H", 1), ("e", 2), ("l", 3), ...]
    
    

    更方便的pattern matching

    除此之外,我们还可以把这种单边的range操作符用在样式匹配中:

    let n = 10
    
    switch n {
    case 6...:
        print(">= 6")
    default:
        break;
    }
    
    

    背后的支持 - RangeExpression

    为了支持单边range操作符的用法,Swift 4在背后,添加了一个protocol RangeExpression,它为各种前缀和后缀版本的单边range操作符定义了接口,大家可以在SE-0172上找到相关的定义,但要说明的是,这份实现,有可能会在未来随着Swift编译器特性的增强而发生变化。所以,当前,我们理解它要表达的含义就好了。

    对源代码的影响

    由于单边range操作符以及RangeExpression都是新增加的内容,因此,它们并不会带来兼容性问题。但是,Swift 3中新增的prefixsuffix方法,会在Swift 4中被标记为过期方法,并在后续的版本中,被删除

    相关文章

      网友评论

          本文标题:更方便的单边Range

          本文链接:https://www.haomeiwen.com/subject/urmuehtx.html