2011-10-28 39 views

Trả lời

20

Trước hết: các lazy trong dòng thứ hai của bạn không được làm bất cứ điều gì, bạn có thể xóa nó và nhận được cùng một kết quả.

Quan trọng hơn: takeWhilethực lười biếng, ở chỗ nó chỉ trả về Stream khác, và không có gì quá khứ người đứng đầu dòng đó sẽ được đánh giá cho đến khi nó cần thiết. Hãy xem xét những điều sau đây:

val s = Stream.from(1).takeWhile(_ > 0) 

Bạn và tôi biết rằng s sẽ là một dòng vô hạn, nhưng nếu chúng ta cháy lên REPL và gõ này trong, nó hoàn toàn hạnh phúc để đánh giá nó:

scala> val s = Stream.from(1).takeWhile(_ > 0) 
s: scala.collection.immutable.Stream[Int] = Stream(1, ?) 

Điều tương tự cũng xảy ra trong ví dụ của bạn: số (Int) ⇒ Boolean mà bạn đã chuyển đến takeWhile sẽ không được đưa bất kỳ yếu tố nào vượt ra ngoài đầu luồng, cho đến khi một cái gì đó như số foreach của bạn làm cho điều đó là cần thiết.

Bạn có thể thấy điều này thậm chí nhiều hơn một cách đáng kể bằng cách thêm một cái gì đó giống như một println bên trong takeWhile ngữ:

scala> val s = Stream.from(1).takeWhile { x => println("Checking: " + x); x < 4 } 
Checking: 1 
s: scala.collection.immutable.Stream[Int] = Stream(1, ?) 

scala> val l = s.toList 
Checking: 2 
Checking: 3 
Checking: 4 
l: List[Int] = List(1, 2, 3) 

Rõ ràng vị chỉ được gọi cho người đứng đầu dòng, cho đến khi chúng tôi buộc các đánh giá phần còn lại của luồng bằng cách gọi toList.

Các vấn đề liên quan