Swift泛型约束中的元组类型

Swift泛型约束中的元组类型,swift,generics,tuples,Swift,Generics,Tuples,我试图用Swift编写一个泛型函数,约束条件是参数必须是成对的序列(我将把它转换成字典)。这可能吗?我尝试了以下几种变体,但编译器不喜欢其中任何一种 func foo<K, V, S: SequenceType where S.Generator.Element == (K,V)>(xs: S) { //...} func-foo(xs:S){/…} 不是对您的问题的直接回答,而是如果您想创建 然后,您可以将函数定义为扩展 方法调用字典,并使用字典定义 typealias Elem

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

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

不是对您的问题的直接回答,而是如果您想创建 然后,您可以将函数定义为扩展 方法调用
字典
,并使用
字典
定义

typealias Element = (Key, Value)
那么您的方法声明可以是

extension Dictionary {
    func foo<S : SequenceType where S.Generator.Element == Element>(xs : S) {
        //...
    }
}
注意:通过上述代码中的
generate()
next()
进行枚举 是一个解决问题的方法,因为某种原因

for (key, value) in xs { }
不编译。比较一下


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

扩展字典{
初始化(xs:S){
self.init()
中的xs.forEach{(键,值)
自[键]=值
}
}
}

在我看来,这像是一个编译器错误

这里的问题是:不能在泛型参数中直接使用元组类型

正如@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"])
structfoo{
typealias元素=(K,V)
静态函数foo(xs:S){
var gen=xs.generate()
而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"]))
struct SequenceOfTuple:SequenceType{
typealias元素=(K,V)
让_generate:()->GeneratorOf
初始值(q:S){
_generate={GeneratorOf(seq.generate())}
}
func generate()->GeneratorOf{
返回_生成()
}
}
func-foo(xs:SequenceOfTuple){
对于xs中的(k,v){
println((k,v))
}
}
foo(SequenceOfTuple([“test”:“foo”,“bar”:“baz”]))
在这种情况下,必须使用
SequenceOfTuple
type包装元组序列,然后将其传递给
foo()


嗯…

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

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
结构矩阵{ 变量容器:[K:[K:V]]=[:] 下标(x:K,y:K)->V{ 得到{ 返回容器[x]?[y] } 设置(值){ 如果容器[x]==nil{ 容器[x]=[:] } 容器[x]![y]=值 } } } 变量矩阵=矩阵() 矩阵[11,42]=“你好,世界” println(“(11,42):\(矩阵[11,42])”//可选(“Hello World”) println(“(1,3):\(矩阵[1,3])”//nil
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"]))
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