Swift:在调用SequenceOf的无参数扩展时缺少参数

时间:2014-10-02 07:32:30

标签: swift arguments ios8 sequence ios8-extension

有谁可以看到这个bug?操场坚持认为参数#2缺失,但没有参数#1!

代码的意图是计算等价值的运行次数,并返回由值及其计数组成的元组序列。我已经广泛地研究了这个代码,对它进行了优化并对其进行了改进,直到我确信它应该可行...但是虽然它编译了,但我不能按照预期的方式调用它。

调用以下代码时出现的错误是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())
                      ^

2 个答案:

答案 0 :(得分: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结尾处有一点(

)。

答案 1 :(得分: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)]

这可以作为Generic Equatable协议问题的通用解决方案。