Swift 什么是';这两种表示映射函数的方法是等价的吗?
今天,当我看到另一个问题时,我感到惊讶:Swift 什么是';这两种表示映射函数的方法是等价的吗?,swift,map-function,Swift,Map Function,今天,当我看到另一个问题时,我感到惊讶: let s = "1,a" let arr = s.split(separator: ",") let result = arr.compactMap{Int($0)} // ok let result2 = arr.compactMap(Int.init) // error 为什么第三行是合法的,而第四行不是?我原以为这两种说法“如果可能,将传入参数强制为Int”是完全等效的 我知道第4行在子序列中阻塞,我知道
let s = "1,a"
let arr = s.split(separator: ",")
let result = arr.compactMap{Int($0)} // ok
let result2 = arr.compactMap(Int.init) // error
为什么第三行是合法的,而第四行不是?我原以为这两种说法“如果可能,将传入参数强制为Int”是完全等效的
我知道第4行在子序列中阻塞,我知道如何摆脱困难:
let result2 = arr.map(String.init).compactMap(Int.init) // ok
我不明白的是,它们为什么不以相同的方式阻塞。看起来像是接受子字符串的
的Int.init
重载具有以下签名:
public init?<S>(_ text: S, radix: Int = 10) where S : StringProtocol
那么这就行了:
let result1 = arr.compactMap(Int.init)
事实上,第一个版本(Int($0)
)调用此初始值设定项,它有两个参数(其中一个具有默认值):
我认为函数引用不能保存任何默认值。不幸的是,我没有找到任何官方的参考资料,但似乎很有趣
证明,最后一个例子:
func test3(param1: String, defaultParam: String = "") { }
let functionReference = test3
functionReference("", "")
functionReference("") // error
这里functionReference的
类型是(String,String)->()
,即使test3
函数有第二个参数的默认值。正如您所看到的,functionReference
不能仅用一个值调用。我试图查找Swift论坛的帖子,其中核心团队中有人解释了这一点,但很抱歉,我找不到它。你可以去那里询问并得到关于这一点的澄清:
默认参数实际上不会产生重载。
相反,在调用站点使用默认参数是使用所有参数的语法甜点。编译器将插入您不使用的默认值
这方面的一些结果…
不能将具有默认参数的函数用作具有简化签名的闭包。正如您在问题中所演示的,您必须将它们包装在新的闭包中
funcƒ(_:Int=0){
让intToVoid:(Int)->Void=ƒ//编译
//无法将类型“(Int)->()”的值转换为指定的类型“()->Void”
让voidToVoid:()->Void=ƒ
具有不同默认参数模式的方法(在调用站点上看起来相同)不被视为重写
类基{
funcƒ(_:Any?=nil)->字符串{“Base”}
}
最终派生类:Base{
//不需要“覆盖”。
funcƒ()->字符串{“派生”}
}
Base().ƒ()/“Base”
派生().ƒ()/“派生”
(派生()
默认参数不允许满足协议要求
协议{
funcƒ()->字符串
}
//类型“Base”不符合协议“protocol”
扩展基:协议{}
是Int.init
实际上是init吗?@ahezeInt(…)
是Int.init
。一个是电话,另一个是名字。用括号提供函数名,这就是我要做的。问题是,为什么这与我在大括号中使用的函数不完全相同。正如我所说,我可以旋转第4行使其工作,我只是不明白为什么我必须这样做。@matt,在评论之前没有注意到你的编辑:)这两个答案说明了为什么。我发现有两个地方在我想使用时经常无法使用.init
,因为缺少重载。默认参数是一个,您在这里遇到的。另一个是自动关闭:@Jessy我仍然觉得这在语言学上很奇怪,Int()
本身并不是Int.init
的语法糖。我猜这是因为函数引用的逻辑和语法不同;它必须是明确的。
@inlinable public init?<S>(_ text: S, radix: Int = 10) where S : StringProtocol
extension Int {
init?<S>(_ string: S) where S: StringProtocol {
// convert somehow, e.g: self.init(string, radix: 10)
return nil
}
}
let result2 = arr.compactMap(Int.init)
func test1<S>(param1: S) -> String where S: StringProtocol {
return ""
}
func test2<S>(param1: S, defaultParam: String = "") -> String where S: StringProtocol {
return ""
}
extension Sequence {
func customCompactMap<ElementOfResult>(_ transform: (Element) -> ElementOfResult?) -> [ElementOfResult] {
compactMap(transform)
}
}
arr.customCompactMap(test1)
arr.customCompactMap(test2) // error
func test3(param1: String, defaultParam: String = "") { }
let functionReference = test3
functionReference("", "")
functionReference("") // error