不带“.”的 Scala 函数调用(点)与使用“。” (点)
Scala function call without "." (dot) vs using "." (dot)
谁能帮我理解这里发生了什么。我有这个生成素数的定义:
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)
}
}
如您所见,这两个定义完全相似,除了第二个没有 .
过滤器之前,而第一个有。
问题是 运行 第一个按预期运行并给我们质数,但第二个产生 java.lang.WhosebugError
。
有人可以阐明这一点吗?在这两种情况下传递给过滤器的是什么?
Scala version: 2.11.6
Java version: 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)
}
}
你需要括号:
def primes: Stream[Long] = {
2 #:: 3 #:: 5 #:: 7 #::(Stream.iterate(11L)(_ + 2) filter {
n => primes takeWhile (p => p*p <= n) forall (n % _ != 0)
})
}
根据经验,我通常到处都使用点。它更易于阅读并使此类错误更难出现。
不带 .
的符号与任何自定义中缀的优先级相同。所以第一个只适用于 filter
Stream.iterate(11L)(_ + 2)
- 第二个适用于 2 #:: 3 #:: 5 #:: 7 #::Stream.iterate(11L)(_ + 2)
.
第一个起作用的原因是过滤器运行时元素 2、3、5 和 7 已经在 primes
中,因此当过滤器尝试使用 primes
时,那些元素已经在里面了。
在第二个代码中情况并非如此,因为过滤器也应用于这些元素,这意味着它们不会出现在 primes
中,直到过滤器 returned 对它们为真。但是过滤器需要先从素数中获取元素,然后才能 return 任何东西,因此它在尝试获取元素时会在无限递归中迷失自己。
谁能帮我理解这里发生了什么。我有这个生成素数的定义:
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)
}
}
如您所见,这两个定义完全相似,除了第二个没有 .
过滤器之前,而第一个有。
问题是 运行 第一个按预期运行并给我们质数,但第二个产生 java.lang.WhosebugError
。
有人可以阐明这一点吗?在这两种情况下传递给过滤器的是什么?
Scala version: 2.11.6
Java version: 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)
}
}
你需要括号:
def primes: Stream[Long] = {
2 #:: 3 #:: 5 #:: 7 #::(Stream.iterate(11L)(_ + 2) filter {
n => primes takeWhile (p => p*p <= n) forall (n % _ != 0)
})
}
根据经验,我通常到处都使用点。它更易于阅读并使此类错误更难出现。
不带 .
的符号与任何自定义中缀的优先级相同。所以第一个只适用于 filter
Stream.iterate(11L)(_ + 2)
- 第二个适用于 2 #:: 3 #:: 5 #:: 7 #::Stream.iterate(11L)(_ + 2)
.
第一个起作用的原因是过滤器运行时元素 2、3、5 和 7 已经在 primes
中,因此当过滤器尝试使用 primes
时,那些元素已经在里面了。
在第二个代码中情况并非如此,因为过滤器也应用于这些元素,这意味着它们不会出现在 primes
中,直到过滤器 returned 对它们为真。但是过滤器需要先从素数中获取元素,然后才能 return 任何东西,因此它在尝试获取元素时会在无限递归中迷失自己。