为什么这不起作用?
"abcdefg".characters.map(String.init) // error: type of expression is ambiguous without more context
Run Code Online (Sandbox Code Playgroud)
在Swift中我喜欢的一个非常酷的东西是能够通过传入一个init方法将一个东西的集合转换为另一个东西(假设存在init()for该类型).
这是一个将元组列表转换为实例的示例ClosedInterval.
[(1,3), (3,4), (4,5)].map(ClosedInterval.init)
Run Code Online (Sandbox Code Playgroud)
这个例子还利用了这样一个事实,即只要元组与函数的参数列表匹配,我们就可以将参数元组作为单个参数传递.
这是另一个例子,这次将数字列表转换为字符串实例.
(1...100).map(String.init)
Run Code Online (Sandbox Code Playgroud)
不幸的是,下一个例子不起作用.在这里,我试图将一个字符串拆分为单字符字符串列表.
"abcdefg".characters.map(String.init) // error: type of expression is ambiguous without more context
Run Code Online (Sandbox Code Playgroud)
map()应该在一个列表上运行Character(事实上,我能够在游乐场中验证Swift推断出正确的[Character]类型被传递到这里map).
String绝对可以从a实例化Character.
let a: Character = "a"
String(a) // this works
Run Code Online (Sandbox Code Playgroud)
有趣的是,如果角色各自都在自己的数组中,这就有效.
"abcdefg".characters.map { [$0] }.map(String.init)
Run Code Online (Sandbox Code Playgroud)
或等效的:
let cx2: [[Character]] = [["a"], ["b"], ["c"], ["d"]]
cx2.map(String.init)
Run Code Online (Sandbox Code Playgroud)
我知道我可以这样做:
"abcdefg".characters.map { String($0) }
Run Code Online (Sandbox Code Playgroud)
但我特意试着理解为什么"abcdefg".characters.map(String.init)不起作用(IMO这种语法也更具可读性和优雅性)
rin*_*aro 14
简化repro:
String.init as Character -> String
// error: type of expression is ambiguous without more context
Run Code Online (Sandbox Code Playgroud)
这是因为String有两个接受一个的初始化器Character:
init(_ c: Character)
init(stringInterpolationSegment expr: Character)
Run Code Online (Sandbox Code Playgroud)
据我所知,当使用初始化程序作为值时,无法消除它们的歧义.
至于(1...100).map(String.init),String.init被称为Int -> String.虽然有两个初始化器接受一个Int:
init(stringInterpolationSegment expr: Int)
init<T : _SignedIntegerType>(_ v: T)
Run Code Online (Sandbox Code Playgroud)
泛型类型比显式类型弱.因此编译器stringInterpolationSegment:在这种情况下选择一个.您可以通过command+点击确认.init.