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

时间:2017-06-29 15:09:34

标签: swift

我想做这样的事情:

var x = ["10","20",30"]
var y = x.map(Int.init)

但我收到此错误

  

对成员' init()'

的模糊引用

我知道我可以写

var y = x.map { Int($0) }

但我想知道是否还有其他办法。

2 个答案:

答案 0 :(得分:5)

问题是,Int初始化程序不存在 String参数。

only exists

init?(_ text: String, radix: Int = default)

虽然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)
    }
}

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

现在你可以说:

let x = ["10", "20", "30"]
let y = x.map(Int.init) // [Optional(10), Optional(20), Optional(30)]

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

这也适用于flatMap(_:)

let y = x.flatMap(Int.init) // [10, 20, 30]

还将过滤转换中的nil元素(不可转换为整数的字符串)。

答案 1 :(得分:1)

问题归结为无法将具有默认参数的函数(例如Int.init(_ text: String, radix: Int = default))分配给只有在默认参数“不存在”时才能“适合”的地方。

当您自己关闭{ Int($0) }时,您告诉编译器您希望应用radix的默认值。不幸的是,这不会隐含地发生。