Scala函数调用没有"." (点)vs使用"." (点)

sma*_*c89 2 stack-overflow primes scala operator-precedence lazy-sequences

有人可以帮我理解这里发生了什么.我有这个定义来生成素数:

def primes: Stream[Long] = {
    2 #:: 3 #:: 5 #:: 7 #::Stream.iterate(11L)(_ + 2).filter {
        n => primes takeWhile (p => p*p <= n) forall (n % _ != 0)
    }
}
Run Code Online (Sandbox Code Playgroud)
def primes: Stream[Long] = {
    2 #:: 3 #:: 5 #:: 7 #::Stream.iterate(11L)(_ + 2) filter {
        n => primes takeWhile (p => p*p <= n) forall (n % _ != 0)
    }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,两个定义完全相似,除了第二个定义没有.前过滤器,而第一个定义具有前置过滤器.

问题是运行第一个,按预期运行并给我们素数,但第二个产生一个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)
    }
}
Run Code Online (Sandbox Code Playgroud)

sep*_*p2k 8

没有的表示法.具有与任何自定义中缀相同的优先级.所以第一个仅适用filterStream.iterate(11L)(_ + 2)- 第二个适用于2 #:: 3 #:: 5 #:: 7 #::Stream.iterate(11L)(_ + 2).

第一个工作的原因是元素2,3,5和7 primes在过滤器运行时已经存在,因此当过滤器尝试使用时primes,这些元素已经在其中.

在第二个代码中并非如此,因为过滤器也应用于这些元素,这意味着primes在过滤器为它们返回true之前它们不会出现.但是过滤器需要在返回任何内容之前从prime中获取元素,因此在尝试获取元素时它会在无限递归中丢失.

  • @ smac89 http://www.scala-lang.org/docu/files/ScalaReference.pdf第6.12节,第84页.6.12.3专门讨论中缀运算符和优先级 (2认同)