2016-09-16 2 views
1

스위프트 2에서는 어떤 시퀀스 (예 : (String, Int))에서 작동하는 함수를 작성할 수있었습니다. 자신의 순서 유형이 튜플로 구성대로, 같은 [String:Int] 같은 사전을 받아 들일 수 있도록 제한된 유형은 특히 유용으로 튜플을 사용스위프트 3에서 일반 시퀀스 매개 변수를 튜플로 제한하는 방법은 무엇입니까?

func test<T: SequenceType where T.Generator.Element == (String, Int)>(input: T) { 
    for (k, v) in input { 
     print(k, "=", String(v)) 
    } 
} 

: 그것은 같은 것을 보았다. 스위프트 3에서

, 나는 유사한 기능이 될 것이다 믿습니다

func test<T: Sequence>(input: T) where T.Iterator.Element == (String, Int) { 
    for (k, v) in input { 
     print(k, "=", String(v)) 
    } 
} 

그러나 예를 들어, [String:Int] 전달을 시도 : 지금까지와 같은

Generic parameter 'T' could not be inferred

: test(input: ["a": 1, "b": 2])는 오류를 발생 내가 알 수 있듯이 Swift 3의 사전은 (Key, Value) 튜플을 이터레이터 유형으로 사용하므로이 방법이 효과가 있다고 생각합니다. 사실 where T.Iterator.Element == String과 같이 제한된 반복기 유형으로 단일 유형을 사용하지 않으면 [String]과 같이 전달할 수 있으며 제대로 작동합니다.

내가 빠진 것이 있거나 스위프트 3의 회귀가 될 수 있습니까?

답변

1

흥미로운 예입니다.

는 이제 Sequence에 부합 대해 Dictionary의 정의를 확인하자 다음 DictionaryIterator

public func makeIterator() -> DictionaryIterator<Key, Value> 

과 :

public mutating func next() -> (key: Key, value: Value)? 

그래서, Dictionary를 들어, T.Iterator.Element(key: Key, value: Value)하지 (Key, Value) 것으로 보인다.

test(input: ["a": 1, "b": 2]) 

을하지만이 작동하지 않습니다 :이 작품

func test<T: Sequence>(input: T) where T.Iterator.Element == (key: String, value: Int) { 
    for (k, v) in input { 
     print(k, "=", String(v)) 
    } 
} 

:

test(input: [("a", 1),("b",2)]) //->Generic parameter 'T' could not be inferred 

을 잘 모르겠어요 이것이 의도

당신이 함수를 다시 작성하는 경우

기능 또는 회귀의 일종, 또는 단순히 버그.

+0

실제로 저는 튜플이 이제 레이블에 대해 더 엄격하다는 것을 기억하고 있다고 생각합니다. 따라서 기능 일 수 있습니다. 나는 내가 그것을 발견 할 수 있는지 알 것이다. ... – Robert

+0

나는 그것을 지금 발견 할 수 없다. 그러나 이것은 기본적으로 나에게 문제를 해결한다. 감사! – Robert

1

이는 알려진 버그 (SR-992)로, 어떤 경우 컴파일러가 동일한 유형이지만 다른 레이블의 튜플과 일치하지 못하게합니다. (String, Int) 또는 (key: String, value: Int) 튜플 모두 통과 시퀀스 및 사전 [String : Int]을 허용 할

하나의 가능한 해결 방법은 입력으로서 요소 (key: String, value: Int) 시퀀스를 예상하는 기능 test(input:) 과부하 될 것이다. 그런 다음 튜플 레이블을 '지우려면'느리게 평가 된 map을 사용한 다음 해당 시퀀스를 원래 구현 test에 전달하십시오.

// Overload to deal with [String : Int] inputs – workaround for a bug. 
func test<T: Sequence>(input: T) where T.Iterator.Element == (key: String, value: Int) { 
    // 'Erase' the tuple labels with a lazily evaluated map(_:) 
    // and pass the sequence onto the original implementation of test(input:) 
    test(input: AnySequence(input.lazy.map{($0.key, $0.value)})) 
} 

func test<T: Sequence>(input: T) where T.Iterator.Element == (String, Int) { 
    for (k, v) in input { 
     print(k, "=", v) 
    } 
} 

let d = ["foo" : 5] 
let a = [("key", 3)] 

test(input: d) // prints: foo = 5 
test(input: a) // prints: key = 3 

아마도 가장 이상적인 해결책은 아니지만이 문제에 대한 다른 쉬운 해결 방법은 없습니다. 누군가가 더 좋은 아이디어를 갖고 있다면 분명 관심이있을 것입니다.

+0

감사합니다. 따라서 버그입니다. 해결 방법에 너무 불편하지는 않지만 잘하면 곧 수정 될 것입니다! – Robert

관련 문제