调用toSet是否缺少参数类型错误?

Ste*_* B. 12 scala type-inference

尝试从字符列表中生成映射到其频率的唯一字符列表 - 例如:

List('a','b','a') -> List(('a',2), ('b',1))
Run Code Online (Sandbox Code Playgroud)

所以,只是在控制台中乱窜,这有效:

val l = List('a', 'b', 'c', 'b', 'c', 'a')       
val s = l.toSet                                  
s.map(i => (i, l.filter(x => x == i).size))
Run Code Online (Sandbox Code Playgroud)

但是,仅通过组合最后2行缩短不?

l.toSet.map(i => (i, l.filter(x => x == i).size)) 
Run Code Online (Sandbox Code Playgroud)

给出错误"缺少参数类型".

有人可以解释为什么Scala会抱怨这种语法吗?

Rex*_*err 22

当你说val s = l.toSet编译器认为唯一明智的类型toSetChar- 这是最具体的选择.然后,鉴于这s是一组Char,编译器意识到地图必须来自a Char.

但在第二种情况下,它拒绝判断元素的类型是什么toSet.它可能会Char,但AnyVal也会起作用Any.

l.toSet.map((i: Any) => (i, l.filter(x => x == i).size))
Run Code Online (Sandbox Code Playgroud)

通常规则是编译器应该选择最具体的值.但是因为函数在它们的参数中是逆变的,所以当它们Any作为参数时它们是最具体的,因此编译器无法决定.可能存在打破平局的规则("更喜欢早期假设"),但没有实施.所以它要求你的帮助.

您可以在函数参数或toSet修复问题时提供类型:

l.toSet.map((i: Char) => (i, l.filter(x => x == i).size))
l.toSet[Char].map(i => (i, l.filter(x => x == i).size))
Run Code Online (Sandbox Code Playgroud)