为什么这段代码不起作用:
scala> List('a', 'b', 'c').toSet.subsets.foreach(e => println(e))
<console>:8: error: missing parameter type
List('a', 'b', 'c').toSet.subsets.foreach(e => println(e))
^
但是当我拆分它然后工作正常:
scala> val itr=List('a', 'b', 'c').toSet.subsets
itr: Iterator[scala.collection.immutable.Set[Char]] = non-empty iterator
scala> itr.foreach(e => println(e))
Set()
Set(a)
Set(b)
Set(c)
Set(a, b)
Set(a, c)
Set(b, c)
Set(a, b, c)
此代码也可以:
Set('a', 'b', 'c').subsets.foreach(e => println(e))
答案 0 :(得分:6)
首先,有一个更简单的代码版本具有相同的问题:
List('a', 'b', 'c').toSet.foreach(e => println(e))
这不起作用
List('a', 'b', 'c').toBuffer.foreach(e => println(e))
然而,这些工作正常:
List('a', 'b', 'c').toList.foreach(e => println(e))
List('a', 'b', 'c').toSeq.foreach(e => println(e))
List('a', 'b', 'c').toArray.foreach(e => println(e))
如果你去查看List
class documentation,你会看到有效的方法返回一些用A
参数化的类型,而不起作用的方法返回用{{1}参数化的类型}}。问题是Scala编译器无法确定使用哪个B >: A
!这意味着如果您告诉它类型它将起作用:
B
现在为什么 List('a', 'b', 'c').toSet[Char].foreach(e => println(e))
和toSet
有签名,我不知道......
最后,不确定这是否有用,但这也有效:
toBuffer
更新:稍微调试一下文档后,我注意到该方法适用于所有带有协变类型参数的类型,但带有< em> invariant 类型参数在返回类型中具有// I think this works because println can take type Any
List('a', 'b', 'c').toSet.foreach(println)
。有趣的是,尽管{1}在Scala中是不变的,但它们提供了两个版本的方法(一个带有B >: A
,另一个带有Array
),这就是为什么它没有这个错误。
我也从未真正回答为什么将表达式分成两行。当您只是单独调用A
时,编译器会自动将B >: A
推断为toSet
的结果A
,除非您确实给它一个特定类型挑。这就是类型推断算法的工作原理。但是,当你将另一个未知类型抛入混合(即lambda中B
的类型)时,推理算法会扼杀并死掉 - 它只能处理一个未知的{{ 1}}以及未知类型的Set[B]
。