簡體   English   中英

Swift泛型約束中的元組類型

[英]Tuple-type in Swift generic constraint

我試圖在Swift中編寫一個泛型函數,其約束條件是該參數必須是成對的序列(我將把它變成字典)。 這可能嗎? 我已經嘗試了以下幾種變體,但是編譯器不喜歡其中任何一種。

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

不是您問題的直接答案,但是如果您想創建字典,則可以將函數定義為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 { }

不編譯。 比較Swift中的實現Set.addSequence


更新: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
        }
    }
}

在我看來,這似乎是一個編譯器錯誤。

這里的問題是:您不能直接在通用參數中使用元組類型。

就像@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類型包裝元組SequenceOfTuple ,然后將其傳遞給foo()

嗯...

您可以將結構體與下標一起使用,並將結果存儲在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