一尘不染

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

swift

我想做这样的事情:

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

但是我得到这个错误

对成员’init()’的不明确引用

我知道我可以写

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

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


阅读 246

收藏
2020-07-07

共1个答案

一尘不染

问题在于不存在 具有参数的Int初始化程序。 __String

目前只存在

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从转换中过滤掉元素(不可转换为整数的字符串)。

2020-07-07