是否可以将Int.init传递给Swift中的函数?

B R*_*son 2 swift

我想做这样的事情:

var x = ["10","20",30"]
var y = x.map(Int.init)
Run Code Online (Sandbox Code Playgroud)

但是我得到了这个错误

对成员'init()'的模糊引用

我知道我可以写

var y = x.map { Int($0) }
Run Code Online (Sandbox Code Playgroud)

但我想知道是否还有另一种方式.

Ham*_*ish 5

问题是,不存在一个Int具有初始化器只有一个String参数.

目前只存在:

init?(_ text: String, radix: Int = default)
Run Code Online (Sandbox Code Playgroud)

尽管radix:参数具有默认值,但只有初始化程序的调用位置处的编译器才会"填充"该参数.

获取对函数本身的引用时,不会部分应用默认参数值,编译器也不会为所有可能的默认参数值组合生成额外的重载.后者不仅会给您的代码增加大量膨胀,而且两个选项都会破坏依赖于在调用站点插入的默认参数值(例如#file&#line).

为了使其正常工作,函数值本身必须支持默认参数值,这带来了相当多的复杂性.虽然很可能是语言的未来版本支持的东西.

获得所需行为的一个简单解决方案是编写一个扩展,在Int该扩展上添加一个init(_:)初始化,然后转发到init(_:radix:):

extension Int {
    /// Creates a new integer value from the given base-10 integer string, returning nil
    /// if the string is in an invalid format.
    init?(_ string: String) {
        // we're saying (_:radix:) in order to disambiguate the call, the compiler
        // will insert the default parameter value of radix: for us.
        self.init(_:radix:)(string)
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,在Swift 4中,这可能是一个扩展FixedWidthInteger,它提供init(_:radix:)了标准库的整数类型的实现.

现在你可以说:

let x = ["10", "20", "30"]
let y = x.map(Int.init) // [Optional(10), Optional(20), Optional(30)]
Run Code Online (Sandbox Code Playgroud)

因为Int.init现在是指我们的扩展初始化器.

这也适用于flatMap(_:):

let y = x.flatMap(Int.init) // [10, 20, 30]
Run Code Online (Sandbox Code Playgroud)

这也将过滤掉nil转换中的元素(不可转换为整数的字符串).