2016-09-13 21 views
6

Khi tôi gọiBản đồ Scala có phải là lười biếng không?

System.err.println("Before") 
System.err.flush() 
val foo: Map[Int, T] = t mapValues (fn(_)) 
System.err.println(foo.head) //prevent optimiser from delaying the construction of 'foo' 
System.err.println("After") 
System.err.flush() 

với fn có một tuyên bố gỡ lỗi in bên trong, tôi nhận được kết quả này:

Before 
...head item... 
After 
...debug print statement from fn... 
...debug print statement from fn... 

Tôi không hiểu tại sao những điều khoản debug in đang được gọi sau "Sau khi" được in và tôi không hiểu tại sao tôi lại nhận được hai lần --- trừ khi mapValues tạo bản đồ lười biếng?

Trả lời

8

Yes it is. Nó ánh xạ tới một lớp trung gian nắm giữ fn và không đánh giá cho đến khi truy cập (lặp đi lặp lại).

def mapValues[W](f: V => W): Map[K, W] = new MappedValues(f) 

Sử dụng nghiêm ngặt map nếu bạn không muốn đánh giá lười biếng. Đó là:

collection map { case (k, v) => (k, fn(v)) } 
+1

Tính năng quan trọng là bạn không cần phải phục hồi bản đồ sau 'mapValues', bởi vì các phím không thay đổi. Với ví dụ 'map' từ bạn, trình biên dịch không thể đảm bảo. – dveim

4

Hãy ghi nhớ rằng việc thực hiện MappedValues đánh giá chức năng trên tất cả các truy cập - khác nhau từ một Scala lazy val mà chỉ đánh giá một lần. Bạn có thể thấy đầu ra hai lần khi bước qua mã. Mở rộng val foo trong cửa sổ trình gỡ lỗi sẽ lặp qua các giá trị, gọi hàm fn và tạo đầu ra gỡ lỗi.

Nếu bạn cung cấp mã cho bản đồ t và chức năng fn, khi đó chúng tôi có thể trợ giúp.

+0

Thật tốt - chủ yếu là hành vi không mong muốn (như mọi khi) không ổn định và cần được theo dõi, thay vì gây ra sự cố cụ thể. Nhưng cảm ơn bạn đã đề nghị giúp đỡ. – Mohan

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