Something như đó là một ý tưởng tốt, nhưng tôi muốn làm cho nó một phương pháp:
def cleanly[A,B](resource: => A)(cleanup: A => Unit)(code: A => B): Option[B] = {
try {
val r = resource
try { Some(code(r)) }
finally { cleanup(r) }
} catch {
case e: Exception => None
}
}
(lưu ý rằng chúng tôi chỉ bắt một lần, nếu bạn thực sự muốn có một thông điệp được in trong một trường hợp và không khác, sau đó bạn phải bắt cả hai như bạn đã làm). (Cũng lưu ý rằng tôi chỉ bắt ngoại lệ; bắt Error
cũng thường là không khôn ngoan, vì nó hầu như không thể phục hồi từ). Phương pháp này được sử dụng như sau:
cleanly(new FileOutputStream(path))(_.close){ fos =>
Iterator.continually(in.read).takeWhile(_ != -1).foreach(fos.write)
}
Kể từ khi nó trả về một giá trị, bạn sẽ nhận được một Some(())
nếu thành công ở đây (bạn có thể bỏ qua).
Chỉnh sửa: để làm cho tổng quát hơn, tôi thực sự sẽ trả lại số Either
thay vào đó, vì vậy bạn sẽ có ngoại lệ. Giống như vậy:
def cleanly[A,B](resource: => A)(cleanup: A => Unit)(code: A => B): Either[Exception,B] = {
try {
val r = resource
try { Right(code(r)) } finally { cleanup(r) }
}
catch { case e: Exception => Left(e) }
}
Bây giờ nếu bạn nhận được Right
, tất cả đều ổn. Nếu bạn nhận được Left
, bạn có thể chọn ngoại lệ của mình. Nếu bạn không quan tâm đến ngoại lệ, bạn có thể sử dụng .right.toOption
để ánh xạ nó thành một tùy chọn hoặc chỉ sử dụng .right.map
hoặc bất kỳ điều gì để hoạt động trên kết quả chính xác chỉ khi nó ở đó (giống như với Option
). (Kết hợp mẫu là một cách hữu ích để xử lý Either
s.)
Nguồn
2012-01-14 22:47:27
Bởi vì tôi cần để có thể tổ nhiều trường java.lang.AutoCloseable, mỗi trong số đó phụ thuộc vào người trước đó đã thành công ngay lập tức, cuối cùng tôi đã đạt được một mô hình rất hữu ích đối với tôi. Tôi đã viết nó như là một câu trả lời cho câu hỏi tương tự StackOverflow: http://stackoverflow.com/a/34277491/501113 – chaotic3quilibrium