Như được thảo luận trong bài đăng trên blog của Eric Lippert Closing over the loop variable considered harmful, việc đóng biến vòng lặp trong C# có thể có hậu quả không mong muốn. Tôi đã cố gắng để hiểu nếu cùng một "gotcha" áp dụng cho Scala.Đóng trên biến vòng lặp trong Scala
Trước hết, vì đây là một câu hỏi Scala, tôi sẽ cố gắng giải thích Eric Lippert của C# ví dụ thêm một vài ý kiến để mã của ông
// Create a list of integers
var values = new List<int>() { 100, 110, 120 };
// Create a mutable, empty list of functions that take no input and return an int
var funcs = new List<Func<int>>();
// For each integer in the list of integers we're trying
// to add a function to the list of functions
// that takes no input and returns that integer
// (actually that's not what we're doing and there's the gotcha).
foreach(var v in values)
funcs.Add(()=>v);
// Apply the functions in the list and print the returned integers.
foreach(var f in funcs)
Console.WriteLine(f());
Hầu hết mọi người mong đợi chương trình này để in 100, 110, 120 Nó thực sự in 120, 120, 120. Vấn đề là chức năng () => v
chúng tôi thêm vào danh sách funcs
đóng trên v biến, chứ không phải là giá trị. Khi giá trị thay đổi v, trong vòng đầu tiên, tất cả ba đóng chúng tôi thêm vào danh sách funcs
"xem" cùng biến v, mà (vào thời điểm chúng ta áp dụng chúng trong vòng thứ hai) có giá trị 120 cho tất cả chúng.
tôi đã cố gắng để dịch mã ví dụ để Scala:
import collection.mutable.Buffer
val values = List(100, 110, 120)
val funcs = Buffer[() => Int]()
for(v <- values) funcs += (() => v)
funcs foreach (f => println(f()))
// prints 100 110 120
// so Scala can close on the loop variable with no issue, or can it?
Liệu Scala thực sự không bị vấn đề tương tự hoặc đã tôi chỉ dịch đang Eric Lippert của nặng và đã thất bại trong việc tái tạo nó?
Hành vi này đã vấp phải rất nhiều nhà phát triển C# dũng cảm, vì vậy tôi muốn đảm bảo không có gotchas tương tự lạ với Scala. Nhưng cũng có thể, một khi bạn hiểu tại sao C# hoạt động theo cách của nó, đầu ra của mã ví dụ của Eric Lippert có ý nghĩa (đó là cách đóng cửa hoạt động, về cơ bản): vậy Scala làm gì khác?
'v' không phải là biến có thể thay đổi trong mã Scala. Hãy nhớ rằng 'for' comprehensions là _not_' for' loops. Mã Scala thực sự chuyển thành một cái gì đó có chức năng hơn rất nhiều so với một vòng lặp 'for' chuẩn, vì vậy, nơi bạn có một' v' với nhiều giá trị trong mã C#, bạn có nhiều 'v' mà mỗi giá trị của riêng chúng trong mã Scala. – Destin
@Destin: cảm ơn, bạn nên đăng câu trả lời đó. Tôi sẽ có ít nhất upvoted nó. (Bạn vẫn có thể làm điều đó, thực sự) –