Swift 在闭包调用程序中使用泛型

Swift 在闭包调用程序中使用泛型,swift,generics,closures,overloading,Swift,Generics,Closures,Overloading,我有两个重载函数,我正试图使用它们在调用方中的签名来调用它们。例如: func sum(_ i: Int, _ s: Int){ print("sum \(i+s)") } func sum(_ i: String, _ s: Int){ var res: String=""; for _ in 1...s{ res += i } print("Repeat \(res)") } func sumCaller<T>

我有两个重载函数,我正试图使用它们在调用方中的签名来调用它们。例如:

func sum(_ i: Int, _ s: Int){
print("sum \(i+s)")
}

func sum(_ i: String, _ s: Int){
var res: String="";
for _ in 1...s{
    res += i
}
print("Repeat \(res)")
}

func sumCaller<T>(_ f: T){
print(type(of: f)) // compiler prints the value is function (Int,Int)->Void !!!
}

sumCaller(sum as (Int, Int)->Void)
编译器抛出错误:

错误:测试。错误:68:5:错误:无法调用非函数类型“T”f(1,3)的值。


但它仍然是作为
sumCaller
参数传递的相同函数。请,有人能解释一下我的错误吗?

我不确定你的目标是什么,但下面的代码是“做点什么”。希望这就是你想要的:

func sum(_ i: Int, _ s: Int){
    print("sum \(i+s)")
}

func sum(_ i: String, _ s: Int){
    var res: String="";
    for _ in 1...s{
        res += i
    }
    print("Repeat \(res)")
}

func sumCaller<A, B>(_ f: (A, B) -> Void, a: A, b: B) {
    print(type(of: f)) // compiler prints the value is function (Int,Int)->Void !!!
    f(a, b)
}

sumCaller(sum, a: 2, b: 3)
sumCaller(sum, a: "Test", b: 3)
func和(i:Int,s:Int){
打印(“总和\(i+s)”)
}
func和(i:String,s:Int){
var-res:String=“”;
对于1…s中的uu{
res+=i
}
打印(“重复\(res)”)
}
func sumCaller(f:(A,B)->Void,A:A,B:B){
print(type(of:f))//编译器打印的值是function(Int,Int)->Void!!!
f(a,b)
}
sumCaller(总和,a:2,b:3)
sumCaller(总和,a:“测试”,b:3)

我不确定你的目标是什么,但下面的代码“做了些什么”。希望这就是你想要的:

func sum(_ i: Int, _ s: Int){
    print("sum \(i+s)")
}

func sum(_ i: String, _ s: Int){
    var res: String="";
    for _ in 1...s{
        res += i
    }
    print("Repeat \(res)")
}

func sumCaller<A, B>(_ f: (A, B) -> Void, a: A, b: B) {
    print(type(of: f)) // compiler prints the value is function (Int,Int)->Void !!!
    f(a, b)
}

sumCaller(sum, a: 2, b: 3)
sumCaller(sum, a: "Test", b: 3)
func和(i:Int,s:Int){
打印(“总和\(i+s)”)
}
func和(i:String,s:Int){
var-res:String=“”;
对于1…s中的uu{
res+=i
}
打印(“重复\(res)”)
}
func sumCaller(f:(A,B)->Void,A:A,B:B){
print(type(of:f))//编译器打印的值是function(Int,Int)->Void!!!
f(a,b)
}
sumCaller(总和,a:2,b:3)
sumCaller(总和,a:“测试”,b:3)

当您使用泛型函数时,
T
是占位符类型名,而不是您已经知道的实际类型名。占位符可以是任何类型,包括
String
Dictionary
Int
等。只有在调用函数时,才会插入实际类型以代替
T
。用实际类型替换泛型类型的过程称为专门化或解析泛型类型。为了解析泛型,编译器要求对这
T
是什么没有歧义,否则它将抛出一个错误,这就是这里发生的情况

当您查看此代码时:

func myFunc(_ : Int, _ : Int) { print("it worked") }
let f : Any = myFunc
print(type(of: f)) // (Int, Int) -> ()
func-sumCaller(f:T){
print(type(of:f))//编译器打印的值是function(Int,Int)->Void!!!
f(1,3)
}

不可能调用此函数并用实际类型替换
T
,这意味着,
T
仍然是占位符,可以是任何类型。例如,
f
可以是
String
类型,这意味着
f(1,3)
等同于
String(1,3)
,这没有意义。编译器让您知道,
T
可能是什么仍然存在歧义。

当您使用泛型函数时,
T
是占位符类型名,而不是您已经知道的实际类型名。占位符可以是任何类型,包括
String
Dictionary
Int
等。只有在调用函数时,才会插入实际类型以代替
T
。用实际类型替换泛型类型的过程称为专门化或解析泛型类型。为了解析泛型,编译器要求对这
T
是什么没有歧义,否则它将抛出一个错误,这就是这里发生的情况

当您查看此代码时:

func myFunc(_ : Int, _ : Int) { print("it worked") }
let f : Any = myFunc
print(type(of: f)) // (Int, Int) -> ()
func-sumCaller(f:T){
print(type(of:f))//编译器打印的值是function(Int,Int)->Void!!!
f(1,3)
}

不可能调用此函数并用实际类型替换
T
,这意味着,
T
仍然是占位符,可以是任何类型。例如,
f
可以是
String
类型,这意味着
f(1,3)
等同于
String(1,3)
,这没有意义。编译器让您知道,对于什么是
T
,仍然存在模糊性。

我认为,如果您忘记了T和泛型,只考虑编译器知道什么,而不是运行时的真实情况,那么最容易理解这一点

首先考虑以下代码:

func myFunc(_ : Int, _ : Int) { print("it worked") }
let f : Any = myFunc
print(type(of: f)) // (Int, Int) -> ()
正如我的评论所指出的,这些代码编译并运行,并打印
(Int,Int)->()
。但这是一个运行时打印。当应用程序运行时,运行时会查看
f
到底是什么,并将其打印出来

但在代码运行之前很久,它就必须编译。编译器只知道如何在外部键入内容。就编译器而言,
f
是一个Any,仅此而已。您知道
f
是一个函数,但编译器不知道

因此,现在我们将在代码中添加一行,它将不再编译:

func myFunc(_ : Int, _ : Int) { print("it worked") }
let f : Any = myFunc
print(type(of: f))
f(1,2) // cannot call value of non-function type 'Any'
你看到了吗?编译器不知道
f
中有函数。它只看到
f
,这是一个Any。直到运行时,
f
才会有一个可以检查的真实值

我们可以通过强制编译器相信这将在运行时变成一个函数来解决问题:

func myFunc(_ : Int, _ : Int) { print("it worked") }
let f : Any = myFunc
print(type(of: f)) // (Int, Int) -> ()
(f as! (Int,Int) -> ())(1,2) // it worked
该编译器编译并运行,函数被成功调用,我们知道这是因为它输出了
“它工作了”

发生了什么事?我们使用
作为(强制转换)告诉编译器放弃自己的信念,盲目接受我们的断言,即当应用程序运行时,
f
将成为一个函数。因此,编译器让我们假装这是真的,去掉它的反对意见,让我们运行代码。我们说了实话,所以我们的代码也成功运行了

但是,如果我们撒谎了——如果
f
是其他类型的东西——那么编译器仍然不会反对,但是我们的应用程序会在
as强制转换

func myFunc(_ : Int, _ : Int) { print("it worked") }
let f : Any = 1
print(type(of: f)) // (Int, Int) -> ()
(f as! (Int,Int) -> ())(1,2) // crash

我认为,如果你忘记了T和泛型,只考虑编译器知道什么,而不是ru中什么是真的,这将是最容易理解的