2014-10-02 65 views
1

任何人都可以看到這個bug的亮點?操場上堅持認爲#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

嗯...那有效。不是我想要的,但我想做鏈接。 – 2014-10-02 13:13:17

0

我找到了更好的答案!謝謝Nate讓我走上正軌。

訣竅是比較器需要來自頂級,其中類型是定義的。所以,最終的解決方案只有三個變化,第二行,第十六行和通話。改變是通過比較器,並使用比較器而不是直接壓縮這些值。

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)] 

然後,這可以作爲通用等式協議問題的一般解決方案。