2014-10-02 3 views
1

누구든지이 버그에 대해 조명을 볼 수 있습니까? 놀이터는 주장 # 2가 빠져 있다고 주장하지만, 주장 # 1은 없다!Swift : SequenceOf의 인수없는 확장 호출에 누락 된 인수

동등한 값의 실행 수를 세고 값과 그 수로 구성된 튜플 시퀀스를 반환하기위한 코드의 의도. 필자는이 코드를 광범위하게 작업하여 최적화하고 최적화 할 때까지 수정했습니다 ... 컴파일되지만 의도 한대로 호출 할 수는 없습니다.

내가 코드를 호출 얻을 오류는 아래 missing argument for parameter #2 in call

extension SequenceOf { 
    func CountRuns<T: Equatable>() -> SequenceOf<(T, Int)> { 
     return SequenceOf<(T, Int)>([]) 
     return SequenceOf<(T, Int)> {() -> GeneratorOf<(T, Int)> in 
      var generator = self.generate() 
      var previousValue: T? 
      var start = true 
      return GeneratorOf<(T, Int)> {() -> (T, Int)? in 
       var count = 1 
       var retValue: (T, Int)? 
       while(true) { 
        var value = generator.next() as T? 
        if start { 
         previousValue = value 
         start = false 
        } else if value != nil && value! == previousValue! { 
         count++ 
        } else { 
         if previousValue != nil { 
          retValue = (previousValue!, count) 
         } 
         previousValue = value 
         break 
        } 
       } 
       return retValue 
      } 
     } 
    } 
} 

println(SequenceOf(y).CountRuns()) 

Playground execution failed: <EXPR>:327:23: error: missing argument for parameter #2 in call 
println(SequenceOf(y).CountRuns()) 
        ^

답변

1

문제는 데있어 당신이 실제로 더의 일반적인 하위 유형을 전문으로하는 방법 제네릭 형식을 확장 할 수 있다는 것입니다. 즉, countRuns 메서드는 SequenceOf의 일반 하위 유형 TEquatable 일 필요가 있지만 이러한 제약 조건은 확장이 아닌 원래 유형 선언에서만 제공 할 수 있습니다.

용액과 같이, 최상위 레벨의 함수로서 countRuns 선언하는 것이다

func countRuns<T: Equatable>(s: SequenceOf<T>) -> SequenceOf<(T, Int)> { 
    return SequenceOf<(T, Int)> {() -> GeneratorOf<(T, Int)> in 

     // note the change from self.generate() to s.generate() here 
     var generator = s.generate() 

     var previousValue: T? 
     var start = true 
     return GeneratorOf<(T, Int)> {() -> (T, Int)? in 
      var count = 1 
      var retValue: (T, Int)? 
      while(true) { 
       var value = generator.next() as T? 
       if start { 
        previousValue = value 
        start = false 
       } else if value != nil && value! == previousValue! { 
        count++ 
       } else { 
        if previousValue != nil { 
         retValue = (previousValue!, count) 
        } 
        previousValue = value 
        break 
       } 
      } 
      return retValue 
     } 
    } 
} 

println(countRuns(SequenceOf(y))) 

this NSHipster article의 끝에서 (작은)을 덮었다.

+0

음 ... 그 작품. 내가 쇠사슬을 만들고 싶기 때문에 내가 원하는 것을 원하지 않습니다. –

0

더 나은 답변을 찾았습니다. 저를 올바른 길로 인도 해 주신 Nate에게 감사드립니다.

트릭은 비교기가 유형이 정의 된 최상위 레벨에서 올 필요가 있다는 것입니다. 따라서 최종 솔루션에는 두 번째 줄, 16 번째 줄 및 통화에서 세 가지 변경 사항 만 있습니다. 변경은 비교기를 전달하고 직접 값을 비교하는 대신 비교기를 사용하는 것입니다.

extension SequenceOf { 
    func CountRuns(areEqual: (T, T) -> Bool) -> SequenceOf<(T, Int)> { 
     return SequenceOf<(T, Int)>([]) 
     return SequenceOf<(T, Int)> {() -> GeneratorOf<(T, Int)> in 
      var generator = self.generate() 
      var previousValue: T? 
      var start = true 
      return GeneratorOf<(T, Int)> {() -> (T, Int)? in 
       var count = 1 
       var retValue: (T, Int)? 
       while(true) { 
        var value = generator.next() as T? 
        if start { 
         previousValue = value 
         start = false 
        } else if value != nil && areEqual(value!, previousValue!) { 
         count++ 
        } else { 
         if previousValue != nil { 
          retValue = (previousValue!, count) 
         } 
         previousValue = value 
         break 
        } 
       } 
       return retValue 
      } 
     } 
    } 
} 

let y = [0, 0, 0, 2, 2, 2, 3, 4 ,4, 5, 65, 65] 
println(SequenceOf(y).CountRuns(==).ToArray()) 
let z = [0.0, 0.0, 0.0, 2.0, 2.0, 2.0, 3.0, 4.0, 4.0, 5.0, 65.0, 65.0] 
println(SequenceOf(z).CountRuns(==).ToArray()) 

// Prints: 
// [(0, 3), (2, 3), (3, 1), (4, 2), (5, 1), (65, 2)] 
// [(0.0, 3), (2.0, 3), (3.0, 1), (4.0, 2), (5.0, 1), (65.0, 2)] 

이것은 Generic Equatable 프로토콜 문제에 대한 일반적인 해결책으로 작동합니다.