Tôi sẽ hỏi điều này với một ví dụ Scala, nhưng nó cũng có thể là điều này ảnh hưởng đến các ngôn ngữ khác cho phép lai phong cách bắt buộc và chức năng.Làm cách nào để tránh vô tình nắm bắt phạm vi địa phương trong các hàm chức năng?
Dưới đây là một ví dụ ngắn (CẬP NHẬT, xem dưới đây):
def method: Iterator[Int] {
// construct some large intermediate value
val huge = (1 to 1000000).toList
val small = List.fill(5)(scala.util.Random.nextInt)
// accidentally use huge in a literal
small.iterator filterNot (huge contains _)
}
Bây giờ iterator.filterNot
công trình một cách lười biếng, đó là rất tốt! Kết quả là, chúng tôi hy vọng rằng trình lặp trở lại sẽ không tiêu thụ nhiều bộ nhớ (thực sự, O (1)). Đáng buồn thay, tuy nhiên, chúng tôi đã thực hiện một sai lầm khủng khiếp: vì filterNot
là lười biếng, nó giữ một tham chiếu đến hàm số huge contains _
. Vì vậy, trong khi chúng tôi nghĩ rằng phương pháp này sẽ đòi hỏi một lượng lớn bộ nhớ trong khi nó đang chạy, và bộ nhớ đó có thể được giải phóng ngay sau khi kết thúc phương pháp, trên thực tế bộ nhớ bị kẹt cho đến khi chúng ta quên Iterator
.
(Tôi chỉ cần thực hiện như một sai lầm, mà mất một thời gian dài để theo dõi xuống! Bạn có thể bắt những việc như vậy nhìn vào đống bãi ...)
thực hành tốt nhất để tránh vấn đề này là gì?
Dường như giải pháp duy nhất là kiểm tra cẩn thận các hàm chức năng tồn tại ở cuối phạm vi và bắt các biến trung gian. Đây là một chút khó xử nếu bạn đang xây dựng một bộ sưu tập không nghiêm ngặt và lập kế hoạch trả lại nó. Bất cứ ai có thể nghĩ về một số thủ thuật tốt đẹp, Scala cụ thể hoặc cách khác, mà tránh vấn đề này và cho tôi viết mã đẹp?
CẬP NHẬT: ví dụ tôi đã đưa ra trước đó là ngu ngốc, như câu trả lời của huynhjl dưới đây minh họa. Nó đã là:
def method: Iterator[Int] {
val huge = (1 to 1000000).toList // construct some large intermediate value
val n = huge.last // do some calculation based on it
(1 to n).iterator map (_ + 1) // return some small value
}
Thực tế, bây giờ tôi đã hiểu rõ hơn về những điều này hoạt động như thế nào, tôi không quá lo lắng!
Huh, quả thật vậy! Tôi sẽ cố gắng đưa ra một ví dụ tốt hơn vào ngày mai, nhưng bây giờ tôi đang bối rối * tại sao * bạn đang nhìn thấy những gì bạn đã làm. Bất cứ ai có thể đưa ra một bản tóm tắt tốt về các biến cục bộ nào được chụp bởi hàm đó theo nghĩa đen? –