2014-10-02 66 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)] 

然后,这可以作为通用等式协议问题的一般解决方案。