2017-06-29 96 views
1

我想要做这样的事情:是否可以将Int.init传递给Swift中的函数?

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

,但我得到这个错误

暧昧参考成员 '的init()'

我知道我可以只写

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

但我想知道是否有其他方式。

+0

您能详细说明一下您的需求吗? – Sajjon

+2

[在map()中使用init()]的可能重复(https://stackoverflow.com/questions/33906791/using-init-in-map)。 –

+0

@MartinR很好找。有趣的是编译器不能消除初始化器的歧义。有时候你会很幸运,像'[false,true] .map(!)'这样的东西可以工作。 – JAL

回答

5

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

only exists

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元素(即不转换为整数的字符串)。

+0

不错!但是'y'仍然返回'[Int?]',可能不需要_optional_Ints。然后你可以在扩展中使用这个init结合'flatMap'来代替map' – Sajjon

+1

@Sajjon Yup,刚刚在添加的过程中,当你评论:)不清楚哪两个OP想要,但想了想提到它并没有什么坏处。 – Hamish

+0

不错! @ b-roy-dawson,你也可以使用这个解决方案,并把它扩展到[String]。像这样:'扩展数组其中元素==字符串{整数:[Int] { return flatMap(Int.init) } }'with * usage:*'var y = x.integers' – Sajjon

1

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

当你自己关闭,{ Int($0) },你告诉编译器你想要默认值radix适用。这不幸的是,这并不是隐含的。

相关问题