2012-03-25 36 views
10

Thông thường nếu bạn tạo một đối tượng Stream, người đứng đầu sẽ được háo hức đánh giá:Khi nào thì đầu của luồng được đánh giá?

scala> Stream({println("evaluating 1"); 1} , 2, 3) 
evaluating 1 
res63: scala.collection.immutable.Stream[Int] = Stream(1, ?) 

Nếu chúng ta tạo ra một Stream mà chúng ta thêm vào trước trong báo cáo kết quả tương tự, có vẻ như hơi ngạc nhiên khi người đứng đầu không được đánh giá trước khi kết nối. ví dụ:

scala> 0 #:: Stream({println("evaluating 1"); 1} , 2, 3) 
res65: scala.collection.immutable.Stream[Int] = Stream(0, ?) 

(#:: là phải kết hợp và là phương pháp thêm vào trước trên ConsWrapper, mà là một lớp tiềm ẩn của Stream.)

Làm thế nào thực hiện điều này không đánh giá người đứng đầu của nó trước khi thêm vào trước 0? Có phải là Stream Stream (hoặc cons cells) không tồn tại trên heap cho đến khi chúng ta lấy các giá trị từ Stream resultant? Nhưng nếu vậy, làm cách nào chúng ta gọi phương thức #:: trên một đối tượng chưa tồn tại?

+1

Tôi khuyên bạn nên sử dụng 'javap' để hiểu điều gì đang diễn ra. –

+0

Tôi đã tìm ra nguồn (giả sử câu trả lời của tôi là chính xác) –

Trả lời

7

-Xprint:typer là bạn của bạn, bất cứ lúc nào bạn muốn hiểu chính xác cách một số mã được đánh giá hoặc loại được suy ra.

scala -Xprint:typer -e '0 #:: Stream({println("evaluating 1"); 1} , 2, 3)' 

val x$1: Int = 0; 
Stream.consWrapper[Int](Stream.apply[Int]({ 
    println("evaluating 1"); 
    1 
}, 2, 3)).#::(x$1) 

Tham số consWrapper là tên. Vì vậy, ngay cả công trình này:

scala> (1 #:: (sys.error("!!"): Stream[Int])).head 
res1: Int = 1 
+0

+1 để sử dụng '-e'. Tôi nghĩ rằng nó được sử dụng rất ít so với, nói, Perl của. –

+0

Tôi nhận ngay bây giờ. Cũng quan trọng là def ngầm từ Stream để ConsWrapper là by-name. 'implicit def consWrapper [A] (luồng: => Luồng [A])'. Đây có lẽ là lý do tại sao 'ConsWrapper' tồn tại, và' # :: 'không phải là một phương thức trên' Stream' trực tiếp: do đó Stream không phải được tạo ra để gọi phương thức này - bạn chỉ nhận được một đối tượng 'ConsWrapper' chứa tập hợp con của chức năng. –

5

Phần đầu được đánh giá tại thời điểm Luồng được tạo.

Nhưng trong ví dụ thứ hai, bạn không vượt qua một Streem làm đối số thứ hai để #:: bạn chuyển một tham số theo tên, tức là biểu thức đầy đủ Stream({println("evaluating 1"); 1} , 2, 3) không được đánh giá.

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