问题描述
我在 Scala-REPL 中输入了以下内容:
I typed the following into the Scala-REPL:
scala> List(1, 2, 3).toSet.subsets(2).map(_.toList)
res0: Iterator[List[Int]] = non-empty iterator
scala> List(1, 2, 3).toSet.subsets.map(_.toList)
<console>:8: error: missing parameter type for expanded function ((x$1) => x$1.toList)
List(1, 2, 3).toSet.subsets.map(_.toList)
为什么第二行出现错误?这是编译器中的错误还是我遗漏了什么?
Why am I getting an error for the second line? Is this a bug in the compiler or am I missing something?
推荐答案
矛盾的是,第一个版本有效,因为应用程序 subsets(2)
中的 subsets
就是这样比没有括号更模棱两可.
Paradoxically, the first version works because subsets
in the application subsets(2)
is, as it were, more ambiguous than without parens.
因为方法重载,在应用程序中,编译器暂停求解toSet
的B
结果,决定B
是 Int
.所以它知道 map
需要什么参数类型.
Because the method is overloaded, in the application, the compiler pauses to solve for the B
result of toSet
, and decides that B
is Int
. So it knows what param type is expected for the map
.
在没有括号的版本中,带参数列表的方法不是候选,因为没有触发eta-expansion.所以当它输入map
应用程序时,它并没有得出任何关于B
的结论,它是映射函数的输入类型.
In the version without parens, the method with a parameter list is not a candidate, because eta-expansion is not triggered. So when it types the map
application, it has not drawn any conclusions about B
, which is the input type to the mapping function.
简单的解决方法是告诉它推导B
:
The easy fix is to tell it to deduce B
:
trait Test {
def f1 = List(1, 2, 3).to[Set].subsets.map(_.toList) // instead of .toSet
def f2 = List(1, 2, 3).toSet.subsets(2).map(_.toList)
}
-Ytyper-debug
在原始代码上的输出显示了重载解析是如何进行类型推断的:
The output of -Ytyper-debug
on the original code shows how overload resolution gooses type inference:
| | | | | | \-> => Iterator[scala.collection.immutable.Set[B]] <and> (len: Int)Iterator[scala.collection.immutable.Set[B]]
| | | | | solving for (B: ?B)
| | | | | |-- 2 : pt=Int BYVALmode-EXPRmode-POLYmode (silent: method f2 in Test)
| | | | | | \-> Int(2)
| | | | | solving for (B: ?B)
| | | | | \-> Iterator[scala.collection.immutable.Set[Int]]
另一种解决方法是通过扩展方法:
Another workaround is to go through an extension method:
scala> implicit class ss[A](val s: Set[A]) { def ss(n: Int) = s subsets n ; def ss = s.subsets }
defined class ss
scala> List(1, 2, 3).toSet.ss.map(_.toList)
res1: Iterator[List[Int]] = non-empty iterator
让我们看看他们是否会改变图书馆:
Let's see if they'll take the library change:
https://github.com/scala/scala/pull/4270
这篇关于Scala:缺少参数类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!