简体   繁体   English

Swift泛型约束中的元组类型

[英]Tuple-type in Swift generic constraint

I'm trying to write a generic function in Swift with the constraint that the parameter must be a sequence of pairs (which I'm going to turn into a dictionary). 我试图在Swift中编写一个泛型函数,其约束条件是该参数必须是成对的序列(我将把它变成字典)。 Is this possible? 这可能吗? I've tried a number of variations on the following, but the compiler doesn't like any of them. 我已经尝试了以下几种变体,但是编译器不喜欢其中任何一种。

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

Not a direct answer to your question, but if you want to create a dictionary then you could define your function as an extension method to Dictionary and use the fact that Dictionary defines 不是您问题的直接答案,但是如果您想创建字典,则可以将函数定义为Dictionary的扩展方法,并使用Dictionary定义的事实

typealias Element = (Key, Value)

Then your method declaration could be 然后你的方法声明可能是

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

To create a dictionary from the tuples, an init method might be more appropriate, for example 要从元组创建字典,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
        }
    }
}

Usage: 用法:

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

Note: The enumation via generate() and next() in above code is a workaround for the problem that, for some reason 注意:上面代码中通过generate()next()进行的枚举是解决由于某种原因而出现的问题的方法

for (key, value) in xs { }

does not compile. 不编译。 Compare Implementing Set.addSequence in Swift . 比较Swift中的实现Set.addSequence


Update: As of Swift 2/Xcode 7, the above method can be simplified to 更新: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
        }
    }
}

It looks like a compiler bug to me. 在我看来,这似乎是一个编译器错误。

Problem here is that: you cannot use tuple type directly in generic parameters. 这里的问题是:您不能直接在通用参数中使用元组类型。

As @MartinR said in his answer, it works if we use typealias ed tuple type. 就像@MartinR在他的回答中说的那样,如果我们使用typealias ed元组类型,它就可以工作。 But of course, we cannot declare generic typealias in global context. 但是,当然,我们不能在全局上下文中声明泛型类型typealias

For example, this compiles and works: 例如,它可以编译并运行:

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

One more idea is something like this: 另一个想法是这样的:

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

In this case, you must wrap the sequence of tuple with SequenceOfTuple type, then pass it to foo() . 在这种情况下,必须使用SequenceOfTuple类型包装元组SequenceOfTuple ,然后将其传递给foo()

Hmm... 嗯...

You can use a struct with a subscript and store the results in a Dictionary: 您可以将结构体与下标一起使用,并将结果存储在Dictionary中:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM