2014-11-13 1 views
5

Dictionary 키를 사용하는 Set in Swift를 구현했습니다. 집합의 요소를 통해 모든 시퀀스 형식을 사용하는 addAll (시퀀스) 메서드를 구현하고 싶지만 이해가되지 않는 오류가 발생합니다. 여기 내 코드가Swift에서 Set.addSequence 구현

struct Set<Element: Hashable> { 
    var hash = [Element: Bool]() 

    init(elements: [Element] = []) { 
     for element in elements { 
      self.hash[element] = true 
     } 
    } 

    var array: [Element] { 
     return hash.keys.array 
    } 

    func contains(element: Element) -> Bool { 
     return hash[element] ?? false 
    } 

    mutating func add(element: Element) { 
     hash[element] = true 
    } 

    mutating func add(array: [Element]) { 
     for element in array { 
      hash[element] = true 
     } 
    } 

    mutating func add<S : SequenceType where S.Generator.Element == Element>(sequence: S) { 
     for element in sequence { // Error here: "Cannot convert the expression's type 'S' to type 'S' 
      hash[element] = true 
     } 
    } 

    mutating func remove(element: Element) { 
     hash[element] = nil 
    } 
} 

이 오류는 XCode 6.1 및 6.0.1에서 발생합니다.

Array의 확장 메소드의 의미를 따르기를 원했지만 그 유형 서명은 나를 위해 컴파일되지 않습니다.

나는 잘못된 것을하고 있습니까, 아니면 레이더 파일을해야합니까?

편집 : 그냥 https://github.com/robrix/Set/blob/master/Set/Set.swift을 발견,이 구현이 있습니다

public mutating func extend<S : SequenceType where S.Generator.Element == Element>(sequence: S) { 
    // Note that this should just be for each in sequence; this is working around a compiler crasher. 
    for each in [Element](sequence) { 
     insert(each) 
    } 
} 

하지만, 그건 그냥 가지 모두 SequenceType의 목적을 패배 Arraysequence 변환합니다.

답변

4

업데이트 :이 문제는 Swift 1.2 (Xcode 6.3 beta 3)에서 수정되었으며 문제의 원래 코드는 오류없이 컴파일됩니다. (스위프트 1.2 기본 Set 유형의 내장을 가지고 있기 때문에, 을 정의하는 것은 사용자 정의 설정 유형은 더 이상 필요하지 않습니다.)


올드 답 : 그것은 나에게 벌레처럼 보이는, 그러나 아마 사람 그것을 설명 할 수 있습니다.

가능한 해결 방법 :

  • 명시 적으로 SequenceOf<Element>sequence 인수를 변환 :

    교체 (https://stackoverflow.com/a/27181111/1187415에서와 같이)
    mutating func add<S : SequenceType where S.Generator.Element == Element>(sequence: S) { 
        for element in SequenceOf<Element>(sequence) { 
         hash[element] = true 
        } 
    } 
    
  • 에 대한 루프의 next()를 사용하는 동안 루프에 의해 시퀀스 생성기를 열고 요소에 명시 적으로 element : Element :

    으로 주석을 달아주세요. map 사용 ("Creating a Set Type in Swift"에서)
    mutating func add<S : SequenceType where S.Generator.Element == Element>(sequence: S) { 
        var gen = sequence.generate() 
        while let element : Element = gen.next() { 
         hash[element] = true 
        } 
    } 
    
  • :

    mutating func add<S : SequenceType where S.Generator.Element == Element>(sequence: S) { 
        map(sequence) { 
         self.hash[$0] = true 
        } 
    } 
    
+0

이 버그에 동의합니다. 누군가보고 했니? 고맙습니다. – drasto

+1

@drasto : 잘 모르겠습니다. 그러나 어떤 경우이 문제의 영향을 받으면 자신의 버그 보고서를 제출하십시오. –

+0

'map '을 사용하는 것이 가장 좋은 해결 방법 인 것 같습니다. 나는 거기에있는 주요한 문제는'map'이 실제로 부작용을 허용해서는 안된다는 것입니다. – bart

3

나는 마틴도 생산지도 솔루션이었습니다 가지고 올 수있는 최선.

mutating func add<S : SequenceType where S.Generator.Element == Element>(sequence: S) { 
    var generator = sequence.generate() 
    while let item = generator.next() { 
     self.hash[item] = true 
    } 
} 

generator.next()에서 또 다른 오류 메시지를 생성합니다 : 흥미롭게도, 수동으로 for 루프를 확장

Cannot convert the expression's type '()' to type 'Self.Element??' 

그것은 수도는하지 않는 대신지도의 감소 사용하기 다소 최적 배열을 삭제하려면 다음을 수행하십시오.

mutating func add<S : SequenceType where S.Generator.Element == Element>(sequence: S) { 
    reduce(sequence,()) { 
     self.hash[$1] = true 
    } 
} 
+0

첫번째 변종은'while let item : Element = generator.next() {..}'로 작업 할 수 있습니다. 'reduce()'로 좋은 아이디어! (하지만 map/reduce는 단지 해킹 일 뿐이므로 간단히'for '는 작동해야합니다.) –

+0

그 오류 메시지는 버그에 대한 창입니다.'for ... in'은 실제로'generate()'를 호출하기 때문에 오류는 'for ... in'도 막을 가능성이 있습니다. –

+0

@MartinR 동의, 단지 더 많은 정보와 옵션을 던지고있었습니다. 확실히 OP가 bugs.apple.com에 게시해야하는 무언가 –