ChatGPT解决这个技术问题 Extra ChatGPT

What is a slice in Swift?

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<Int>) -> Slice<T>

Why not return another Array<T> rather than a Slice<T>?

It looks like I can concatenate a slice with an array:

var list = ["hello", "world"]
var slice: Array<String> = [] + list[0..list.count]

But this yields the error:

could not find an overload for 'subscript' that accepts the supplied arguments

var list = ["hello", "world"]
var slice: Array<String> = list[0..list.count]

What is a slice?


m
matt

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])

That makes sense. Is this described anywhere in the documentation?
It's an implementation detail, really. You cleverly probed the edge case that reveals the workings of the black box...!
actually Slice is copy of array. After you update original array, slice wont change. This is because of struct nature. And for the note, Sliceable protocol do not imply usage of Slice type
The swift language has changed and a slice actually uses three ellipsis and not two developer.apple.com/library/ios/documentation/General/Reference/…
It wouldn't wreck the correspondence if you added a simple edit informing new readers that the range operators have changed?
N
Nate Cook

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"]

In fact, slices works just like arrays, as you say. Swift arrays have mutable elements, even if they're declared as immutable. For example, try let arr = ["hello", "world", "goodbye"]; arr[0] = "bonjour". You'll find it works. With immutable arrays, oddly, it's only the size that's immutable, not the content. (See "Mutability of Collections" in The Swift Programming Language)
"Mutable elements" - This is no longer true
C
Chris Conover

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"