Swift의 배열에서 부분열을 꺼내면 Array형이 아닌 ArraySlice형이 된다

환경


  • Swift 3.2.0
  • XCode: 8.3.1

  • Q. String 배열로부터 Range로 꺼낸 부분열의 형태는 [String]가 아니다



    Swift 3에서 배열에서 Range 객체를 사용하여 부분 열을 검색하는 경우 다음과 같은 코드로 구현할 수 있습니다.

    map1.swift
    let strs: [String] = [ "a", "b", "c", "d" ]
    print(strs[0..<2]) // ["a", "b"]
    

    다음에 꺼낸 부분열을 변수에 대입하는 것을 생각합니다.
    평상시 자신은 Swift를 쓸 때 형추론을 사용하지 않고 가능한 한 명시적인 형식 지정을 하는 버릇이 있었습니다.
    또 부분열이므로 , 형도 같은 String 배열일 것이라고 생각해 다음과 같은 코드를 쓴 곳

    map.error.swift
    let strs: [String] = [ "a", "b", "c" ]
    let partOfStrs: [String] = strs[0..<2] // error: ambiguous subscript with base type '[String]' and index type 'CountableRange<Int>'
    

    그리고 화가났다 ...
    error: ambiguous subscript with base type '[String]' and index type 'CountableRange<Int>'
    

    그게 도대체 ...

    평소 Ruby등을 쓰고 있어 String 배열의 부분열의 형태는 당연[String]일 것이라는 감각이었으므로, 왜 에러가 되는지 모르게 빠져 버렸습니다

    A. Swift의 배열은 Array형, Range에서 꺼낸 부분 배열은 ArraySlice형



    오류를 보면 검색된 부분 열을 「[String]ではない」라고 합니다.

    그래서 만약을 위해 형을 조사해 보겠습니다.

    type.swift
    let strs: [String] = [ "a", "b", "c", "d" ]\
    print(String(describing: type(of: strs)))
    let partOfStrs:  = strs[0..<2]
    print(String(describing: type(of: partOfStrs)))
    

    결과
    > Array<String>
    > ArraySlice<String>
    

    가 되어, Array가 아니라 ArraySlice 라고 하는 형태가 되어 있었습니다.

    실은 Swift에서는 배열로부터 부분열을 꺼낸 경우, ArraySlice라는 형태로 객체가 생성됩니다
    이 ArraySlice는 원래의 Array와 거의 같은 인터페이스를 가지면서, 실태로서는 원의 Array 객체에의 View가 되어 있습니다.

    Apple 공식을 보면

    The ArraySlice type makes it fast and efficient for you to perform operations on sections of a larger array.Instead of copying over the elements of a slice to new storage, an ArraySlice instance presents a view onto the storage of a larger array. And because presents the same interface as Array, you can generally perform the same operations on a slice as you could on the original array.

    번역: ArraySlice 형은 큰 배열의 부분열에 대한 처리를 고속으로 효율적으로 한다. 새 스토리지에 요소를 복사하는 대신 ArraySlice 인스턴스는 원래 큰 배열에 대한 View를 나타냅니다. 한편, ArraySlice는 Array와 같은 인터페이스를 가지고 있기 때문에, 대부분의 경우에 있어서 원래의 Array로 하는 것과 같은 처리가 슬라이스에 대해서도 가능하다.

    그리고 있습니다.
    그래서 평소 사용하고있는 분에는 Array와 ArraySlice의 차이를 신경 쓸 필요는없는 것 같습니다.

    다만 방금의 코드와 같이 형추론을 사용하지 않고, 명시적으로 대입하면 당연히 형이 다르다고 하는 것으로 화내고 있었던 것이군요
    세세한 일입니다만, 다른 언어로부터 오면 빠져서 「 」가 되기 때문에 메모해 둡니다.

    참고


  • ArraySlice - Swift Standard Library | Apple Developer Documentation
  • Swift에서 배열에서 값을 꺼내려고 할 때 오류를 토했다.
  • arrays - Ambiguous Use of Subscript in Swift - Stack Overflow
  • 좋은 웹페이지 즐겨찾기