2016-06-24 11 views
-1

Xcode 8 베타를 사용하면 두 번째 확장명을 컴파일 할 수 없습니다. 이것이 신속한 버그인지 알려진 제한인지 이해할 수 없습니다.Swift 형식 시스템이 형식을 잘못된 예상 매개 변수로 변환하려고 시도합니다.

extension Array { 
    func scanl<T>(initial: T, combine:(Iterator.Element, T) -> T) -> [T] { 
     guard let first = self.first else { return [] } 
     return [initial] + Array(self.dropFirst()).scanl(initial: combine(first, initial), combine: combine) 
    } 
} 


extension Array { 
    func scanl<T>(combine: (Iterator.Element, T) -> T) -> [T] { 
     guard let first = self.first else { return [] } 
     return Array(self.dropFirst()).scanl(initial:first, combine:combine)// Cannot convert value of type '(Element, T) -> T' To expected argument type '(_, _) -> _' 
    } 
} 

(요소, T) -> T는 실제로 함수 유형입니다. 그래서 내가 컴파일러 (,)을 기대하는 이유를 이해할 수 없다 - __ >와

+0

각 호출마다 전체 배열을 복사하므로'O (n^2)'의 시간 복잡도로 이어지기 때문에 여기서 재귀를 사용하지 않는 것이 좋습니다. 당신은'for'-loop를 사용하는 것보다 낫습니다. –

답변

1

이 버그 또는 제한되지 않습니다 "내가 유형에 대해 걱정하지 않는다"옆에이 형태가 무엇을 의미, 그것은 단순히이다 컴파일러가 컴파일시에 first이 두 번째 확장자에 T 유형 (T이 반드시 Iterator.Element과 같을 필요는 없음)을 확인하는 것이 불가능합니다. 두 클로저에서 컴파일러는 firstIterator.Element 유형임을 알고 있지만 컴파일러는 이것이 T 유형인지 여부를 알 수 없습니다.

첫 번째 확장에서는 combine 클로저의 첫 번째 인수로 first을 사용합니다.이 유형은 Iterator.Element 유형만을 필요로하므로 모두 양호합니다. 두 번째 연장에서

, 그러나, 당신은 T을 입력 것으로 예상 매개 변수 (initial)에 인수로 first을 통과하려고 시도하고, 컴파일러에 의해 사용되는 first 정말 유형 T (같은 종류 T인지 여부를 알 수 없다 두 개의 인수 scanl을 호출하는 데 사용 된 combine 클로저), 즉 Iterator.Elementself 인 것은 T입니다. 이 두 번째 확장의 선택적 바인딩 절에서 first ~ T의 형식 변환 시도()로 쉽게 사용할 수 있습니다.

extension Array { 
    func scanl<T>(combine: (Iterator.Element, T) -> T) -> [T] { 
     guard let first = self.first as? T else { return [] } 
     return Array(self.dropFirst()).scanl(initial: first, combine: combine) 
    } 
} 

다른 유형, 예를 들어 어레이를 구성하는 하나 개의 유형의 어레이를 스캔 일례를 구성하는 경우와 Iterator.ElementT 반드시 동일 형태 일 필요가 없다는 사실은 명백

/* scant [Int] array to construct [String] array */ 
let foo = [1, 2, 3, 4, 5] 
let bar = foo.scanl(initial: "0") { String($0) + $1 } 
print(bar) // ["0", "10", "210", "3210", ""] 

당신은 단지 당신의 scanl 방법 (하나는 스캔으로) 같은 타입의 배열을 생산하는 콜렉터처럼, 당신은 일반적인 T 포함 할 필요 싶지만, 장소에 Iterator.Element 유형을 사용할 수 있다면 위의 확장 프로그램에서 T