Swift通用约束中的元组类型

时间:2015-02-12 10:02:53

标签: swift generics tuples

我试图在Swift中编写一个泛型函数,其约束条件是参数必须是一对对的序列(我将变成一个字典)。这可能吗?我已经尝试了以下几种变体,但编译器并不喜欢它们中的任何一种。

func foo<K, V, S: SequenceType where S.Generator.Element == (K,V)>(xs: S) { //...}

3 个答案:

答案 0 :(得分:6)

不是您问题的直接答案,但如果您想创建 然后你可以将你的函数定义为扩展名 方法Dictionary并使用Dictionary定义

的事实
typealias Element = (Key, Value)

然后你的方法声明可能是

extension Dictionary {
    func foo<S : SequenceType where S.Generator.Element == Element>(xs : S) {
        //...
    }
}

要从元组创建字典,init方法可能更合适,例如

extension Dictionary {

    init<S : SequenceType where S.Generator.Element == Element>(xs : S) {

        self.init()
        var gen = xs.generate()
        while let (key, value) : Element = gen.next() {
            self[key] = value
        }
    }
}

用法:

let d = Dictionary(xs: [("a", 1), ("b", 2)])
println(d) // [b: 2, a: 1]

注意:上述代码中的generate()next()进行了审核 是由于某种原因

的问题的解决方法
for (key, value) in xs { }

无法编译。比较Implementing Set.addSequence in Swift


更新: Swift 2 / Xcode 7 开始,上述方法可以简化 到

extension Dictionary {

    init<S : SequenceType where S.Generator.Element == Element>(xs : S) {
        self.init()
        xs.forEach { (key, value) in
            self[key] = value
        }
    }
}

答案 1 :(得分:0)

对我来说,它看起来像编译器错误。

问题在于:您不能在通用参数中直接使用元组类型

正如@MartinR在他的回答中所说,如果我们使用typealias ed元组类型,它就有效。但是,当然,我们不能在全局上下文中声明泛型typealias

例如,这会编译并运行:

struct Foo<K,V> {
    typealias Element = (K,V)
    static func foo<S:SequenceType where S.Generator.Element == Element>(xs:S) {
        var gen = xs.generate()
        while let (k,v): Element = gen.next() {
            println((k,v))
        }
    }
}

Foo.foo(["test":"foo", "bar": "baz"])

另外一个想法是这样的:

struct SequenceOfTuple<K,V>: SequenceType {

    typealias Element = (K,V)

    let _generate:() -> GeneratorOf<Element>

    init<S:SequenceType where S.Generator.Element == Element>(_ seq:S) {
        _generate = { GeneratorOf(seq.generate()) }
    }
    func generate() -> GeneratorOf<Element> {
        return _generate()
    }
}

func foo<K,V>(xs:SequenceOfTuple<K,V>) {
    for (k, v) in xs {
        println((k,v))
    }
}

foo(SequenceOfTuple(["test":"foo", "bar": "baz"]))

在这种情况下,您必须使用SequenceOfTuple类型包装元组序列,然后将其传递给foo()

嗯...

答案 2 :(得分:0)

您可以使用带有下标的结构并将结果存储在字典中:

struct Matrix<K:Hashable, V> {

    var container:[K:[K:V]] = [:]

    subscript(x:K, y:K) -> V? {
        get {
            return container[x]?[y]
        }
        set (value) {
            if container[x] == nil {
                container[x] = [:]
            }
            container[x]![y] = value
        }
    }
}

var matrix = Matrix<Int, String>()
matrix[11,42] = "Hello World"

println("(11,42): \(matrix[11,42])") // Optional("Hello World")
println("(1,3): \(matrix[1,3])")     // nil