Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 什么是';这两种表示映射函数的方法是等价的吗?_Swift_Map Function - Fatal编程技术网

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吗?@aheze
Int(…)
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