我正在玩scala流。
这是从给定数字开始的所有整数流。
我添加了一个println
来跟踪函数的每个调用。
def from(n: Int): Stream[Int] = n #:: from({ println(n); n + 1 })
val nats = from(0) //> nats : Stream[Int] = Stream(0, ?)
nats.take(4).toList //> 0
//| 1
//| 2
//| 3
//| res0: List[Int] = List(0, 1, 2, 3, 4)
正如预期的那样,这是我的scala工作表的输出。然后我创建了所有素数的流。
def sieve(s: Stream[Int]): Stream[Int] = {
s.head #:: sieve(s.tail.filter({ println( "---" ); _ % s.head != 0 }))
} //> sieve: (s: Stream[Int])Stream[Int]
val primes = sieve(from(2))//> primes : Stream[Int] = Stream(2, ?)
primes.take(4).toList //> 2
//| ---
//| 3
//| 4
//| ---
//| 5
//| 6
//| ---
//| res1: List[Int] = List(2, 3, 5, 7)
问题就出现了。我认为应该稍微改变一下,添加x
参数而不是_
占位符。令人惊讶的是,输出结果完全不同:
def sieve(s: Stream[Int]): Stream[Int] = {
s.head #:: sieve(s.tail.filter(x => { println("---"); (x % s.head) != 0 }))
} //> sieve: (s: Stream[Int])Stream[Int]
val primes = sieve(from(2))//> primes : Stream[Int] = Stream(2, ?)
primes.take(4).toList //> 2
//| ---
//| 3
//| ---
//| 4
//| ---
//| ---
//| 5
//| ---
//| 6
//| ---
//| ---
//| ---
//| res1: List[Int] = List(2, 3, 5, 7)
我不明白为什么所有这些重复。 使用显式参数有什么不对?
答案 0 :(得分:3)
区别在于{ println( "---" ); _ % s.head != 0 }
是{ println( "---" ); x => x % s.head != 0 }
的缩写,而不是{ x => println( "---" ); x % s.head != 0 }
。
在第一种情况下,您首先拨打println
,然后返回该功能,因此---
每filter
次打印一次{};}在第二个中,每次filter
调用被过滤的流的每个元素一次(并且因为sieve
是递归的并且再次过滤流,所以对于每个元素,最终会得到多个---
输出)。
答案 1 :(得分:0)
让我们在两种情况下比较论证和筛子,仔细看看:
s.tail.filter( { println( "---" ); _ % s.head != 0 })
s.tail.filter(x => { println( "--- " + x ); (x % s.head) != 0 })
你看到println电话的区别吗?
现在输出
First: Second:
//> 2 //> 2
//| --- //| --- 3
关键区别:
println( "---" )
println( "--- " + x )
在第二种情况下,您会在破折号后面附加" "+x
,这就是案件之间的确切差异。