Trong bộ sưu tập Scala, nếu ai muốn để lặp qua một bộ sưu tập (mà không trả lại kết quả, tức là làm một tác dụng phụ trên mọi phần tử của bộ sưu tập), nó có thể được thực hiện hoặc vớiScala: "map" vs "foreach" - có lý do nào để sử dụng "foreach" trong thực tế không?
final def foreach(f: (A) ⇒ Unit): Unit
hoặc
final def map[B](f: (A) ⇒ B): SomeCollectionClass[B]
với ngoại lệ của bản đồ có thể lười biếng (*), từ một góc độ người dùng cuối, tôi thấy không khác biệt trong các lời gọi:
myCollection.foreach { element =>
doStuffWithElement(element);
}
myCollection.map { element =>
doStuffWithElement(element);
}
cho rằng tôi chỉ có thể bỏ qua những gì kết quả đầu ra bản đồ. Tôi không thể nghĩ ra bất kỳ lý do cụ thể nào để sử dụng hai phương pháp khác nhau, khi map
dường như bao gồm tất cả chức năng của foreach
, và trên thực tế, tôi sẽ rất ấn tượng nếu một trình biên dịch thông minh & VM sẽ không tối ưu hóa việc tạo đối tượng bộ sưu tập đó vì nó không được gán cho bất kỳ thứ gì, hoặc đọc hoặc sử dụng ở bất kỳ đâu.
Vì vậy, câu hỏi là - tôi có đúng không - và không có lý do gì để gọi foreach
ở bất kỳ đâu trong mã của người đó?
Ghi chú:
(*) Khái niệm bản đồ lười biếng, as throughly illustrated in this question, có thể thay đổi mọi thứ một chút và biện minh cho việc sử dụng của foreach
, nhưng như xa như tôi có thể nhìn thấy, người ta đặc biệt cần phải vấp ngã khi một LazyMap
, bình thường
(**) Nếu một không sử dụng một bộ sưu tập, nhưng viết một, sau đó người ta sẽ nhanh chóng vấp ngã khi thực tế là cú pháp cú pháp for
hiểu là trong thực tế, một đường cú pháp mà tạo ra "Foreach" cuộc gọi, ví dụ: hai dòng sau tạo mã hoàn toàn tương đương:
for (element <- myCollection) { doStuffWithElement(element); }
myCollection.foreach { element => doStuffWithElement(element); }
Vì vậy, nếu ai quan tâm về những người khác sử dụng mà lớp bộ sưu tập với for
cú pháp, người ta vẫn có thể muốn thực hiện foreach
phương pháp.
Thật tuyệt khi sử dụng 'foreach' thay vì' map' để phân biệt giữa các tác dụng phụ và các tác dụng không có tác dụng phụ. Tôi không quan tâm nếu trình biên dịch tối ưu hóa một cho người khác. Sự khác biệt làm cho mục đích của mã rõ ràng hơn. –
Để tiến thêm một bước nữa thì LimbSoup, tôi thích dùng 'for ..' (sans yield) thay vì' .foreach' trực tiếp vì nó (cho tôi) cho thấy sự phân chia giữa lặp * cho * tác dụng phụ và chuyển đổi cho chuỗi. Ngoài ra, nó có thể nguy hiểm để giả định trình tự được lặp lại không phải là lười biếng. – user2864740
Ngược lại với bạn, * I * sẽ rất ấn tượng nếu trình biên dịch Scala hiện tại và/hoặc JVM có thể tối ưu hóa 'bản đồ' thành mã' foreach' nếu kết quả không được sử dụng. Điều này xuất hiện với tôi như là một tối ưu hóa ** vô cùng nhỏ nhặt **. – ziggystar