What is a slice in Swift?

后端 未结 3 1552
甜味超标
甜味超标 2020-12-13 01:16

What is a slice in Swift and how does it differ from an array?

From the documentation, the type signature of subscript(Range) is:

subscript(Range<         


        
相关标签:
3条回答
  • Note: This answer is happily invalid as of Swift beta 3, since arrays are now true value types.


    @matt is correct, above - the Slice<T> points into the array. That seems contrary to the way Swift handles all the other data types we're working with, since it means the value of the slice can change even if it's declared as a constant:

    var arr = ["hello", "world", "goodbye"]    // ["hello", "world", "goodbye"]
    let slice = arr[0..2]                      // ["hello", "world"]
    arr[0] = "bonjour"
    println(slice)                             // ["bonjour", "world"]
    

    The worst part is that the slice acts just like an array. Given that in Swift we have an expectation of immutability it seems dangerous that the subscripted values of the slice can change without warning:

    println(slice[1])                          // "world"
    arr[1] = "le monde"
    println(slice[1])                          // "le monde"
    

    But if the underlying array changes too drastically, they get unhooked:

    arr.removeAtIndex(0)                       // this detaches slice from arr
    println(slice)                             // ["bonjour", "le monde"]
    arr[0] = "hola"
    println(slice)                             // ["bonjour", "le monde"]
    
    0 讨论(0)
  • 2020-12-13 01:54

    Summary:

    The answers above were true up until Beta 3 (and may change again in future releases)

    Slice now acts just like an array, but as @matt said above, is effectively a shallow copy to an array under the hood, until a change is made. Slices (now) see a snapshot of the original values,

    Also note that slice syntax has changed:

    [from..upToButNotIncluding] -> [from..<upToButNotIncluding]
    

    Example:

    var arr = ["hello", "world", "goodbye"] // ["hello", "world", "goodbye"]
    var arrCopy = arr
    let slice = arr[0..<2]                  // ["hello", "world"]
    arr[0] = "bonjour"
    arr                                     // ["bonjour", "world", "goodbye"]
    arrCopy                                 // ["hello", "world", "goodbye"]
    slice                                   // ["hello", "world"]
    

    This allows much more uniform processing, as it is simpler (IMHO) to do python style list processing - filtering one list to make another. per Matt's answer prior to Beta 3, you had to create a temporary array in order to map a slice. The new code is now simpler:

    class NameNumber {
        var name:String = ""
        var number:Int = 0
    
        init (name:String, number:Int) {
            self.name = name
            self.number = number
        }
    }
    
    var number = 1
    let names = ["Alan", "Bob", "Cory", "David"]
    let foo = names[0..<2].map { n in NameNumber(name:n, number:number++) }
    foo     // [{name "Alan" number 1}, {name "Bob" number 2}]
    

    (though to be fair, foo is still a slice)

    Reference:

    http://adcdownload.apple.com//Developer_Tools/xcode_6_beta_3_lpw27r/xcode_6_beta_3_release_notes__.pdf

    Important Changes, Issues Resolved, - Swift Language, Paragraph 1

    "Array in Swift has been completely redesigned to have full value semantics like Dictionary and String...m"

    0 讨论(0)
  • 2020-12-13 02:12

    The slice points into the array. No point making another array when the array already exists and the slice can just describe the desired part of it.

    The addition causes implicit coercion, so it works. To make your assignment work, you would need to coerce:

    var list = ["hello", "world"]
    var slice: Array<String> = Array(list[0..<list.count])
    
    0 讨论(0)
提交回复
热议问题