在Swift中传递函数的泛型类型

时间:2015-02-20 11:10:10

标签: swift generics

为了避免重复代码,我试图找到一种从T类型的变量中推断出参数类型() -> TU的方法。

我不知道我是否足够清楚,所以这就是我不想做的事情:

func f<T>(closure: () -> T) -> String {
    return "closure: () -> \(T.self)"
}
func f<T>(value: T) -> String {
    return "value: \(T.self)"
}

f("test1") // -> "value: Swift.String"
f({ return "test2" }) // -> "closure: () -> Swift.String"

func foo<U>(bar: U) -> (String, String) {
    return ("\(U.self)", f(bar))
}

foo("test3") // (.0 "Swift.String", .1 "value: Swift.String")
foo({ return "test4" }) // (.0 "() -> Swift.String", .1 "value: () -> Swift.String")

我希望foo({ return "test4" })能够调用f<T>(closure: () -> T)函数而不是f<T>(value: T)。为什么Swift无法推断bar: U() -> T模式匹配?

1 个答案:

答案 0 :(得分:2)

TL; DR:使用foo()/ U.

丢失类型数据

我怀疑你是来自C ++背景。

这可以在C ++中使用,因为C ++推断出基于调用站点的类型。 Swift是不同的,因为泛型参数是类型数据的唯一源。在您的情况下,您没有提供有关类型U的信息,因此编译器不知道如何将其转换为闭包类型。你的f()值重写是有效的,因为你没有在T上放置任何条件,而在你的闭包类型覆盖中,你指定了一个特定的形式(一个闭包)。由于所有类型数据都是通过foo调用而丢失的,因为foo采用泛型(认为空白)类型U,编译器没有足够的信息,也无法推断从(空白)到闭包的转换。

这是#34; type reification&#34;的主题,在devforums.apple.com上对此进行了长时间的讨论。