[英]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.