有人可以帮我理解这里发生了什么。我有这个定义来生成素数:
def primes: Stream[Long] = {
2 #:: 3 #:: 5 #:: 7 #::Stream.iterate(11L)(_ + 2).filter {
n => primes takeWhile (p => p*p <= n) forall (n % _ != 0)
}
}
def primes: Stream[Long] = {
2 #:: 3 #:: 5 #:: 7 #::Stream.iterate(11L)(_ + 2) filter {
n => primes takeWhile (p => p*p <= n) forall (n % _ != 0)
}
}
正如您所看到的,两个定义完全相似,只是第二个定义在过滤器之前没有.
,而第一个定义则没有。{/ p>
问题在于运行第一个,按预期运行并为我们提供素数,但第二个产生java.lang.StackOverflowError
。
有人可以对此有所了解吗?在任何一种情况下传递给过滤器的是什么?
Scala版本:2.11.6
Java版本:1.8.0_121
这是我用来测试每个程序的完整程序:
object Main {
def primes: Stream[Long] = {
2 #:: 3 #:: 5 #:: 7 #::Stream.iterate(11L)(_ + 2) filter {
n => primes takeWhile (_ <= sqrt(n)) forall (n % _ != 0)
}
}
def primes2: Stream[Long] = {
2 #:: 3 #:: 5 #:: 7 #::Stream.iterate(11L)(_ + 2).filter {
n => primes2 takeWhile (p => p*p <= n) forall (n % _ != 0)
}
}
def main(args: Array[String]): Unit = {
println(primes.take(args.head.toInt).force)
}
}
答案 0 :(得分:8)
没有.
的表示法具有与任何自定义中缀相同的优先级。因此,第一个仅将filter
应用于Stream.iterate(11L)(_ + 2)
- 第二个将其应用于2 #:: 3 #:: 5 #:: 7 #::Stream.iterate(11L)(_ + 2)
。
第一个工作的原因是当过滤器运行时元素2,3,5和7已经在primes
中,所以当过滤器尝试使用primes
时,这些元素是已经在里面了。
在第二个代码中并非如此,因为过滤器也应用于这些元素,这意味着它们不会出现在primes
中,直到过滤器为它们返回true。但是过滤器需要在返回任何内容之前从prime中获取元素,因此在尝试获取元素时它会在无限递归中丢失。
答案 1 :(得分:2)
你需要括号:
&#xA;&#xA; def primes:Stream [Long] = {&#xA; 2#:: 3#:: 5#:: 7#::(Stream.iterate(11L)(_ + 2)过滤器{&#xA; n =&gt; primes takeWhile(p =&gt; p * p&lt; = n)forall(n%_!= 0)&#xA;})&#xA;}&#xA;
&#xA;&#xA; 作为规则拇指,我通常到处都用点。它更容易阅读,并使这些错误难以出现。
&#xA;