2011-11-14 24 views
5

Xin lỗi nếu câu hỏi này không có ý nghĩa gì.Luồng chương trình - bảo lãnh không hoạt động nếu một phép tính không thành công

Tôi hiện đang ở giữa việc viết một ứng dụng nhỏ và tôi muốn 'chuỗi' một số chức năng với nhau tạo thành một tính toán rộng hơn. Ví dụ:

Ví dụ: tôi có một chức năng gọi một dịch vụ web và trả về một kết quả là hash-map hoặc nil nếu đó là lỗi hoặc đã xảy ra sự cố. Hàm tiếp theo trong chuỗi lấy bản đồ và thực hiện thêm một số xử lý và sau đó chuyển nó sang hàm tiếp theo ... và cứ tiếp tục như vậy. Điều này là nếu chức năng đầu tiên thất bại, nó sẽ vượt qua nil đến chức năng tiếp theo và sẽ ném một nullpointer (hoặc bất cứ điều gì) và tôi không muốn nó thậm chí đạt đến giai đoạn này. Vì vậy, nói cách khác tôi muốn toàn bộ tính toán thất bại nếu một mục trong chuỗi bị lỗi.

ví dụ:

;successful computation = function1 returns W -> function2 returns X -> function3 returns Y -> function4 returns Z -> Z 
;failed computation = function1 returns W -> function2 returns X -> function3 returns nil -> nil 
(-> (function1 "http://webservice.com") (function2) (function3) (function4)) 

Vấn đề là tôi không muốn được xả rác mỗi chức năng của tôi với if(nil? arg) lúc bắt đầu, tốt nhất là tôi muốn một sự trừu tượng mà có thể chăm sóc cho rằng đối với tôi nhưng tôi không thực sự clued lên trên những gì có sẵn trong Clojure

tôi đã nghĩ đến việc áp dụng các Scala phong cách Option kiểu đó có thể là Some(value) hoặc None nhưng tôi vẫn sẽ cần phải xả rác mã của tôi với những kiểm tra vào đầu

Bất kỳ ý tưởng hoặc câu trả lời sẽ thực sự được đánh giá cao

Trả lời

4

's algo.monad bao gồm việc triển khai đơn nguyên mà Scala gọi Option. Nó được gọi là maybe-m và hoạt động bằng cách xử lý nilNone. Bạn có thể sử dụng nó như thế này:

(ns mulk.monads-test 
    (:refer-clojure) 
    (:use clojure.repl 
     clojure.algo.monads)) 

(defn function1 [x] 
    x) 

(defn function2 [x] 
    (+ x 10)) 

(defn function3 [x] 
    (* x 2)) 

(defn calc-stuff [thing] 
    (domonad maybe-m 
    [x1 (function1 thing) 
    x2 (function2 x1) 
    x3 (function3 (+ x2 10))] 
    x3)) 

(calc-stuff 10) ;=> 60 
(calc-stuff nil) ;=> nil 
+0

này awesome là những gì tôi đang tìm kiếm, có vẻ như có một vài trừu tượng khác trong thư viện đó sẽ chứng minh là rất hữu ích đối với tôi nữa! – djhworld

4

clojure.contrib.core có macro -?> thực hiện chính xác những gì bạn muốn.

Xem http://clojuredocs.org/clojure_contrib/clojure.contrib.core/-_q%3E

+0

Aha! Công cụ tuyệt vời. Tôi tự hỏi liệu macro '-?>' Có thực sự chỉ là một trình bao bọc cho phần "có lẽ" được mô tả trong câu trả lời của Matthias không? – djhworld

+0

Không, việc triển khai là khép kín: https://github.com/clojure/clojure-contrib/blob/master/modules/core/src/main/clojure/clojure/contrib/core.clj –

1

Bạn có thể định nghĩa một hàm helper cho chaining các cuộc gọi chức năng và kiểm tra cho các giá trị nil ở giữa:

(defn chain [v & functions] 
    (cond (nil? v) nil 
     (empty? functions) v 
     :else (recur ((first functions) v) (rest functions)))) 

Sau đó gọi nó là như thế này:

(chain "http://webservice.com" function1 function2 function3 function4) 
Các vấn đề liên quan