对于通用标题感到抱歉,如果没有示例,很难描述问题。
假设我定义了以下限制为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]"