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这种语法也更具可读性和优雅)
1条答案
按热度按时间xriantvc1#
简化的再现:
这是因为
String
有两个接受一个Character
的初始化式:据我所知,在使用初始化器作为值时,没有办法消除它们的歧义。
对于
(1...100).map(String.init)
,String.init
被称为Int -> String
。虽然有两个初始化器接受一个Int
:泛型类型比显式类型 * 弱 *。所以编译器在这种情况下选择
stringInterpolationSegment:
。你可以通过命令+点击.init
来确认。