2011-09-07 47 views
6

Tôi đang cố trì hoãn các phép tính khác nhau. Tôi có chức năng của các hình thức sau đây,Đối số chức năng nhiều loại

(defn a-fn [a b] 
    (let [a (if (fn? a) 
      a 
      #(identity a)) 

     b (if (fn? b) 
      b 
      #(identity b))] 
    (+ (a) (b)))) 

này cho phép tôi để vượt qua một-fn, một giá trị hoặc một hàm trả về giá trị,

(a-fn 1 2)  
(defn x [] 1)  
(defn y [] 2)  
(a-fn x y) 
(a-fn x 2) 

những gì tôi làm là xây dựng một danh sách các hàm (giống như ở trên) để hoạt động trên một số dữ liệu, fns có thể sử dụng các fns khác để lấy các đối số của chúng hoặc trong một số trường hợp mọi thứ không thay đổi và chúng được gán giá trị làm đối số. Tôi đã tự hỏi liệu có cách nào tốt hơn để đạt được loại hành vi này?

Trả lời

2

Có thể có một cách thanh lịch hơn để làm những gì bạn muốn, nhưng đây là ít nhất một phiên bản chung chung hơn của nó:

(defn delayed [reducer & fs] 
    (apply reducer (for [f fs] (if (fn? f) (f) f)))) 

(def a-fn (partial delayed +)) 

Vì vậy delayed mất một chức năng tùy ý và một danh sách các chức năng/giá trị. Nếu mở rộng tất cả các args và sau đó áp dụng các chức năng cho họ. Sau đó, chúng tôi sử dụng để xác định partiala-fn bạn sử dụng +:

user=> (a-fn 1 2) 
3 
user=> (a-fn (constantly 1) 2) 
3 
user=> (a-fn (constantly 1) 2 4) 
7 

Ngoài ra, nó có thể có ý nghĩa cho delayed để trả về một hàm thay vì sử dụng một phần. Lưu ý chắc chắn là tốt hơn.

Một tên tốt hơn so với "trì hoãn" được hoan nghênh :)

6

Bạn có thể sử dụng delayforce:

user=> (defn a-fn [a b] (+ (force a) (force b))) 
#'user/a-fn 
user=> (a-fn 1 2) 
3 
user=> (def x (delay 1)) 
#'user/x 
user=> (def y (delay 2)) 
#'user/y 
user=> (a-fn x y) 
3 
user=> (a-fn x 2) 
3 

Nếu bạn cố gắng một cái gì đó giống như (delay (prn :hello) 1) để kiểm tra khi tính toán được thực hiện, lưu ý rằng in ấn đối tượng Delay buộc nó; do đó, (def x (delay ...)) an toàn, nhưng nhập số (delay ...) đồng bằng trong dấu nhắc REPL thì không.

+0

Tốt. Quên về sự chậm trễ/lực lượng. –

Các vấn đề liên quan