我想要做这样的事情:是否可以将Int.init传递给Swift中的函数?
var x = ["10","20",30"]
var y = x.map(Int.init)
,但我得到这个错误
暧昧参考成员 '的init()'
我知道我可以只写
var y = x.map { Int($0) }
但我想知道是否有其他方式。
我想要做这样的事情:是否可以将Int.init传递给Swift中的函数?
var x = ["10","20",30"]
var y = x.map(Int.init)
,但我得到这个错误
暧昧参考成员 '的init()'
我知道我可以只写
var y = x.map { Int($0) }
但我想知道是否有其他方式。
问题是,不存在Int
初始化程序,它只有 a String
参数。
init?(_ text: String, radix: Int = default)
虽然参数有一个默认值,这仅仅是在初始化器的调用点“填充”为您编译器。
当获取对函数本身的引用时,默认参数值不会部分应用,也不会为默认参数值的所有可能组合生成额外的重载。后者不仅会使代码显着膨胀,而且这两个选项都会打破取决于在呼叫站点插入的默认参数值(例如#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)
}
}
注意,在斯威夫特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
元素(即不转换为整数的字符串)。
不错!但是'y'仍然返回'[Int?]',可能不需要_optional_Ints。然后你可以在扩展中使用这个init结合'flatMap'来代替map' – Sajjon
@Sajjon Yup,刚刚在添加的过程中,当你评论:)不清楚哪两个OP想要,但想了想提到它并没有什么坏处。 – Hamish
不错! @ b-roy-dawson,你也可以使用这个解决方案,并把它扩展到[String]。像这样:'扩展数组其中元素==字符串{整数:[Int] { return flatMap(Int.init) } }'with * usage:*'var y = x.integers' – Sajjon
问题归结为不能将具有默认参数的函数(如Int.init(_ text: String, radix: Int = default)
)分配到只有在“默认”参数“不存在”时才能“适合”的地方。
当你自己关闭,{ Int($0) }
,你告诉编译器你想要默认值radix
适用。这不幸的是,这并不是隐含的。
您能详细说明一下您的需求吗? – Sajjon
[在map()中使用init()]的可能重复(https://stackoverflow.com/questions/33906791/using-init-in-map)。 –
@MartinR很好找。有趣的是编译器不能消除初始化器的歧义。有时候你会很幸运,像'[false,true] .map(!)'这样的东西可以工作。 – JAL