2011-02-03 1 views
8

Gần đây tôi đã viết các bit sau của Scala:Tùy chọn có bao gồm một giá trị một mẫu hay không?

val f: File = ... // pretend this file came from somewhere 
val foo = toFoo(io.Source.fromFile(f).mkString) 

tôi thực sự không thích cách này chảy. Để hiểu những gì đang xảy ra, bạn phải bắt đầu với f ở giữa, đọc bên trái để fromFile, đọc ngay để mkString, đọc lại một lần nữa để toFoo. Ugh.

Đặc biệt là sau khi quen với việc chuyển đổi chức năng của chuỗi, điều này rất khó đọc. Lần thử tiếp theo của tôi trông giống như sau:

val foo = Some(f) 
    .map(io.Source.fromFile) 
    .map(_.mkString) 
    .map(toFoo) 
    .get 

Tôi thích luồng này tốt hơn nhiều. Bạn có thể thấy điều gì xảy ra Đây có phải là cách sử dụng tốt của lớp học Option không? Hay tôi lạm dụng nó? Có một mô hình tốt hơn mà tôi có thể sử dụng để đạt được cùng một luồng không?

Trả lời

25

Điều này là hoàn toàn ổn. Tuy nhiên, có một phương pháp |> trong Scalaz mà không một tốt hơn, và bạn có thể tạo ra nó cho mình nếu bạn không muốn tất cả các Scalaz:

class Piper[A](a: A) { def |>[B](f: A => B) = f(a) } 
implicit def pipe_everything[A](a: A) = new Piper(a) 

f |> io.Source.fromFile |> {_.mkString} |> toFoo 

Cá nhân, tôi có xu hướng để viết rất nhiều mã mà đòi hỏi phải có dấu ngoặc và tôi thích phương pháp tốt hơn so với các nhà khai thác trong nhiều trường hợp, vì vậy trong mã của tôi, tôi thường gọi |> "sử dụng", nhưng đó là thỏa thuận tương tự:

f.use(io.Source.fromFile).use(_.mkString).use(toFoo) 

trong Scala 2.11 hoặc mới hơn, bạn có thể nhận được cùng một hành vi và cải thiện performan CE với (hơi) ít cú pháp:

implicit class Piper[A](private val a: A) extends AnyVal { 
    def |>[B](f: A => B) = f(a) 
} 
+0

đó là đoạn trích mà tôi đưa vào mọi dự án tôi viết! Nên ở trong thư viện chuẩn thực sự ... –

+0

@Kevin - Đồng ý, nó phải ở trong thư viện chuẩn. Tôi cũng có nó trong tất cả các dự án của mình vì tôi có một thư viện chuẩn mà tôi bỏ vào mọi dự án tôi viết, và đây là một trong những thứ trong đó. –

+0

Phiên bản cập nhật cho thế hệ hiện tại: 'lớp ẩn Piper [A] (a: A) {def |> [B] (f: A => B) = f (a)} mở rộng AnyVal' –

4

Bạn thêm toFoo để String qua ma cô mẫu thư viện của tôi. Sau đó, nó sẽ trở thành:

val foo = Source fromFile f mkString() toFoo 
+0

Hoặc '(Source fromFile f mkString) toFoo', chỉ là sở thích cá nhân. –

+4

@Kevin Tôi muốn có một biểu tượng có thể đứng cho "không có danh sách tham số". Nếu nó là bắt buộc, nó sẽ giải quyết tất cả các vấn đề ký hiệu postfix. –

5

Tôi không có vấn đề gì với các câu trả lời khác được đưa ra ở đây, nhưng bạn có xem xét thay đổi tên của toFoo thành thứ gì đó 'chảy' tốt hơn không? Ý tôi là, toFoo thực sự có mùi giống như một cái gì đó phải ở trên đúng của một biểu thức, nhưng nếu bạn đổi tên nó thành một thứ khác, nó có thể vừa với còn lại.

// toFoo, as defined by you 
val foo = toFoo(io.Source.fromFile(f).mkString) 
// Same function, different name 
val foo = createFooFrom(io.Source.fromFile(f).mkString) 
+0

Đồng ý, nhưng chỉ là một ví dụ :-) – leedm777