通用参数';T';无法在赋值后推断 //Xcode 11.6/Swift 5 进口基金会 func f(u:(T)->Void){} @可丢弃结果 func g(u:Int)->Int{0} f{g($0)}//编译罚款 f{let}=g($0)}//无法推断泛型参数“T”
在上面的代码中,泛型函数通用参数';T';无法在赋值后推断 //Xcode 11.6/Swift 5 进口基金会 func f(u:(T)->Void){} @可丢弃结果 func g(u:Int)->Int{0} f{g($0)}//编译罚款 f{let}=g($0)}//无法推断泛型参数“T”,swift,generics,Swift,Generics,在上面的代码中,泛型函数f需要一个接受类型为T的参数的函数作为其参数 函数g采用Int类型的参数 当我写f{g($0)}时,代码会编译。我相信(如果我错了,请纠正我),这是因为编译器可以根据g的参数类型推断T是Int 但是,当我尝试使用返回值g执行某些操作时,例如在let=g($0)行中,编译器抱怨它无法再推断T的类型 在我看来,g的返回类型应该与编译器如何推断T的类型无关,但显然它确实如此 有人能解释一下为什么会发生这种情况,以及可以做些什么(如果有的话)来纠正它吗?看起来@discardab
f
需要一个接受类型为T
的参数的函数作为其参数
函数g
采用Int
类型的参数
当我写f{g($0)}
时,代码会编译。我相信(如果我错了,请纠正我),这是因为编译器可以根据g
的参数类型推断T
是Int
但是,当我尝试使用返回值g
执行某些操作时,例如在let=g($0)
行中,编译器抱怨它无法再推断T
的类型
在我看来,g
的返回类型应该与编译器如何推断T
的类型无关,但显然它确实如此
有人能解释一下为什么会发生这种情况,以及可以做些什么(如果有的话)来纠正它吗?看起来@discardableResult让您能够拥有两种类型的函数: g(:Int)->Int和g(:Int)->Void(当您不想使用函数的结果时) 我认为
f{g($0)}
-这里您的f可以推断类型,因为它具有相同的类型
// Xcode 11.6 / Swift 5
import Foundation
func f<T>(_: (T) -> Void) { }
@discardableResult
func g(_: Int) -> Int { 0 }
f { g($0) } // compiles fine
f { let _ = g($0) } // Generic parameter 'T' could not be inferred
f{let}=g($0)}
-在这种情况下,g函数的类型不同于f函数
(_: (T) -> Void) and (_: (Int) -> Void)
如果删除“let”,它将再次编译:
(_: (T) -> Void) and (_: (Int) -> Int)
我认为
f{let}=g($0)}
-仅返回Int值
f{{{ug=g($0)}
-返回函数({:(Int)->Int)
可能是这里的一个键函数f接受一个函数作为参数,而该函数又接受类型为
T
的参数,并且不返回任何内容(Void
)。对于自动推断类型的闭包,它必须由单个(有时是简单的)表达式组成。任何复杂的事情都会使编译器难以推断(从编译器的角度来看,这是有意义的)。显然,就编译器而言,let=g($0)
是一个复杂的语句。有关更多信息,请参阅此这可能是编译器错误,也可能不是
众所周知,Swift不会试图推断某些闭包的类型,即多语句闭包:
这是正确的行为:Swift不会从多语句闭包的主体中推断参数或返回类型
但是,闭包只包含一条语句,具体来说是一条声明。尽管很奇怪,但他们设计它的目的可能是,如果闭包也包含一个声明,Swift就不会试图推断类型。例如,这也不会编译
f { _ = g($0) }
如果这是出于设计,那么它背后的基本原理可能是因为闭包中的单个声明没有多大意义。无论声明什么,都不会被使用
但同样,这只是猜测,这也可能是一个bug
要解决此问题,只需将其作为非a声明:
f { let x: Int = $0 } // nothing to do with "g"! The issue seems to be with declarations
或
在
f{let{ug=g($0)}
中,你认为T是什么,为什么?@matt我认为T
是Int
(或者应该是),因为g
明确地接受Int
。谢谢你链接到SR-1570。现在看来很明显,这是一个预期的行为,而这只是一个缺陷,因为它很难在编译器中实现。显式指定传递给f
的闭包的函数类型修复了问题,例如f{(\ui:Int)->Void in let{=g(i)}
。
f { _ = g($0) } // this, without the "let", is IMO the idiomatic way to ignore the function result
f { g($0) } // g has @discardableResult anyway, so you don't even need the wildcard