2011-09-07 26 views
6

Çeşitli hesaplamaları ertelemeye çalışıyorum. Benİşlev bağımsız değişkenleri çok sayıda

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

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

bu beni-fn, bir değer veya değer döndüren bir fonksiyon,

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

ne yapmam işlevlerin bir listesini oluşturmak olduğunu geçmesine izin verir, aşağıdaki biçimde işlevlere sahiptir Bazı veriler üzerinde çalışmak için (yukarıdaki gibi), fns argümanlarını geri almak için diğer kurbanları kullanabilir veya bazı durumlarda işler değişmez ve argüman olarak değerler atanır. Bu tarz bir davranışa sahip olmanın daha iyi bir yolu olduğunu merak ediyordum?

cevap

2

istediğini yapmak daha zarif bir yolu olabilir, ama burada bunun daha genel bir versiyonu en azından var:

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

(def a-fn (partial delayed +)) 

Yani delayed keyfi fonksiyonu ve fonksiyon/değerler listesi sürer. Tüm argsleri genişletir ve işlevi onlara uygular. Sonra + kullanarak a-fn tanımlamak için partial kullanın:

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

Alternatif olarak, kısmi kullanmak yerine bir işlev dönmek delayed için mantıklı olabilir. Hangisinin daha iyi olduğuna dikkat edin.

"gecikmiş" den daha iyi bir isim karşılama :)

6

Sen delay ve force kullanabilirsiniz şudur: hesaplama yapıldığında test etmek (delay (prn :hello) 1) gibi bir şey denerseniz

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 

, o baskıyı dikkat Gecikme nesnesi onu zorlar; (def x (delay ...)) güvenlidir, ancak REPL istemine (delay ...) düz yazarak değil.

+0

Güzel. Gecikmeyi/zorlamayı unuttum. –

İlgili konular