swift2 在map()中使用init()

4smxwvx5  于 2022-11-06  发布在  Swift
关注(0)|答案(1)|浏览(182)

TL;DR

为什么不管用?

"abcdefg".characters.map(String.init) // error: type of expression is ambiguous without more context

详细信息

Swift中我喜欢的一个非常酷的功能是通过传入init方法(假设存在该类型的init())将一个集合转换为另一个集合。
下面是一个将元组列表转换为ClosedInterval示例的示例。

[(1,3), (3,4), (4,5)].map(ClosedInterval.init)

该示例还利用了这样一个事实:只要元组与函数的参数列表相匹配,我们就可以将参数元组作为单个参数传递。
这是另一个例子,这次将数字列表转换为字符串示例。

(1...100).map(String.init)

不幸的是,下一个例子不起作用。在这里,我试图将一个字符串拆分成一个单字符串列表。

"abcdefg".characters.map(String.init) // error: type of expression is ambiguous without more context

map()应该在Character的列表上操作(实际上,我能够在一个游戏场中验证Swift推断出这里传递给map的[Character]的正确类型)。
String绝对可以从Character示例化。

let a: Character = "a"
String(a) // this works

有趣的是,如果每个字符都在自己的数组中,这就可以了。

"abcdefg".characters.map { [$0] }.map(String.init)

或等效的:

let cx2: [[Character]] = [["a"], ["b"], ["c"], ["d"]]
cx2.map(String.init)

我知道我可以做到这一点:

"abcdefg".characters.map { String($0) }

但我特别试图理解为什么"abcdefg".characters.map(String.init)不起作用(IMO这种语法也更具可读性和优雅)

xriantvc

xriantvc1#

简化的再现:

String.init as Character -> String
// error: type of expression is ambiguous without more context

这是因为String有两个接受一个Character的初始化式:

init(_ c: Character)
init(stringInterpolationSegment expr: Character)

据我所知,在使用初始化器作为值时,没有办法消除它们的歧义。
对于(1...100).map(String.init)String.init被称为Int -> String。虽然有两个初始化器接受一个Int

init(stringInterpolationSegment expr: Int)
init<T : _SignedIntegerType>(_ v: T)

泛型类型比显式类型 * 弱 *。所以编译器在这种情况下选择stringInterpolationSegment:。你可以通过命令+点击.init来确认。

相关问题