對不起,對於通用標題,很難描述沒有例子的問題。這個泛型函數發生了什麼?
假設我定義了被約束到Equatable
類型以下通用功能:
func test<T: Equatable>(expect expected: T, run:() -> T) {
let value = run()
if value == expected {
print("OK")
} else {
print("Expected: \(expected), Actual: \(value)")
}
}
這裏的使用表示函數的例子:
test(expect: 100) { 10 * 10 } // prints "OK"
test(expect: 1000) { 10 * 10 } // prints "Expected: 1000, Actual: 100"
,當然,我可以存儲值,而不是使用文本:
let e = 100
test(expect: e) { e } // prints "OK"
到目前爲止,一切都按預期工作(沒有雙關語)。
現在讓我們來試試這個有一個數組:
test(expect: [1, 2]) { [1, 2] } // prints "OK"
再次,工作的事情了。
但我們現在試試這個:
let a = [1, 2]
test(expect: a) { a } // error: cannot convert value of type '() -> [Int]' to expected argument type '() -> _'
所以我一直在建立的問題是:爲什麼不這項工作?
遊樂場正確推斷的a
類型爲[Int]
,所以來自哪裏的() -> _
的期望?
嘗試了一堆最後一個示例的變化:
test(expect: a) { return a }
test(expect: a) { return a as [Int] }
test(expect: a as [Int]) { return a as [Int] }
test(expect: [1, 2]) { a }
test(expect: [1, 2] as [Int]) { a }
它們都導致了同樣的問題。由於某些原因,Swift似乎認爲該函數預計爲() -> _
。
因此,也許這只是因爲數組不是Equatable
,但這個工程:
let a = [1, 2]
[1, 2] == [1, 2]
a == a
我想我明白仿製藥非常好,而且我完全被這個難住了。這是Swift中的錯誤還是我的定義中的錯誤test()
?目標是否能夠完成?
解決方案
感謝@下面Sulthan的回答,我能寫(以及與此有關的任何SequenceType
)這個函數來處理數組情況下另一個版本:
public func test<T: SequenceType where T.Generator.Element: Equatable>(expect expected: T, run:() -> T) {
let result = run()
// Note: zip() will stop at the shorter array, so this implementation isn't correct, don't use it (it will incorrectly end up saying [1] == [1,2]). This code is just here to demonstrate the function's generic constraint.
let eq = zip(expected, result).filter(!=).isEmpty
if eq {
print("OK")
} else {
print("Expected: \(expected), Actual: \(result)")
}
}
let a: [Int] = [1, 2]
test(expect: [1,2]) { a } // prints "OK"
test(expect: [1,3]) { a } // prints "Expected: [1, 3], Actual: [1, 2]"
答案與http://stackoverflow.com/a/33732669/669586相同,但我不確定是否應該將其作爲副本關閉。 – Sulthan
@Sulthan從它的根本來看,這絕對是一個相同的問題,但通過函數來完成這個事實混淆了這個問題,我覺得它值得站在自己的位置上。此外,問題的一部分是如何做這項工作,這個問題的編輯也解決。 – vopilif
作爲關於我上面的「解決方案」的一個附註。將'test()'的實現約束到'SequenceType'可能是一個壞主意,因爲它有無限序列的有效性,所以你不想試圖迭代所有的序列。 'CollectionType'會更合適。 – vopilif