2012-08-11 10 views
5

üç Arity 1, 2 fonksiyonlarını ve aşağıda 3 olduğunu varsayalım:Karışık bir aritmetik fonksiyon zincirini değerlendirebilir ve gerektiğinde kısmi işlev döndürür?

(defn I [x] x) 
(defn K [x y] x) 
(defn S [x y z] (x z (y z))) 

Clojure değerlendirmek için bir değerlendirme işlevi veya deyim var mı:

(I K S I I) as (I (K (S (I (I))))) 

Arity 2'nin bir parital işlevi dönen?

Yukarıdaki basit işlev tanımlarını alıp kısmi sonuçları döndürebilen çok işlevli işlevlere genişleten bir makro oluşturmayı düşünüyorum. Bunu gerçekleştirmek için zaten yerleşik veya deyimsel bir yol varsa, makro oluşturmak istemem.

(defn I 
    ([x] I x) 
    ([x & more] (apply (I x) more))) 

(defn K 
    ([x] (partial K x)) 
    ([x y] x) 
    ([x y & more] (apply (K x y) more))) 

(defn S 
    ([x] (partial S x)) 
    ([x y] (partial S x y)) 
    ([x y z] (x z (y z))) 
    ([x y z & more] (apply (S x y z) more))) 
+0

Sadece bunu buldum, ve * senin için mükemmel olabileceğini düşündüm, ve başka bir şey değilse, en azından yararlı ... http: //alfredodinapoli.wordpress.com/2011/03/16/a-bit-of -clojure-magic-ve-high-order-functions-are-served/ –

cevap

5

Ben tam Yapmaya çalıştığınız anlamak emin değilim ama comp işlevi bu tür yapmak için kullanışlıdır: Burada

genişletilmiş makro yukarıdaki fonksiyonlar için istiyoruz şeydir "işlev zincirleme" hakkında konuşuyor gibi görünüyorsun. Örneğin: listeyi (I K S I I) varsa lütfen durumda

user> (vec (rest (list 1 2 3 4 5))) 
=> [2 3 4 5] 

ve ben (reduce comp ...) kullanmak istiyorsunuz, (I (K (S (I (I))))) olarak değerlendirmek istiyorum, ama sen yapabilirsin:

user> ((comp vec rest list) 1 2 3 4 5) 
=> [2 3 4 5] 

eşdeğerdir hangi ayrıca (apply comp ...) kullanın.

user> ((reduce comp [vec rest list]) 1 2 3 4 5) 
=> [2 3 4 5] 
user> ((apply comp [vec rest list]) 1 2 3 4 5) 
=> [2 3 4 5] 

Ayrıca -> veya ->> makrolar ilginizi çekebilir. Bu makrolar argümanlarını sırayla bir sonraki argümanlara yerleştirir. -> makrosu, bir sonraki ifadenin ilk konumuna girer, oysa ->> makrosu, sonraki ifadenin son konumuna girer. "Sonraki şey" bir işlev ise, her ikisi de aynı davranacak ve (function nested-things-so-far) bir ifade oluşturacak ve devam edecek.

Gerçekten, örnekler en iyisidir:

(-> 1 (+ 10) (- 100) inc) 
;//Expands to... 
(inc (- (+ 1 10) 100)) 
;//Evaluating in the REPL... 
user> (-> 1 (+ 10) (- 100) inc) 
=> -88 

(->> 1 (+ 10) (- 100) inc) 
;//Expands to... 
(inc (- 100 (+ 10 1))) 
;//Evaluating in the REPL... 
user> (-> 1 (+ 10) (- 100) inc) 
=> 90 

Ancak, (yine, ben tam olarak anladığını sanmıyorum, olsa da) otomatik Currying içeren bir şey yapmak istiyorum daha fazla gibi görünüyor ve bunun için Önceden var olan herhangi bir şeyi bilmiyorum.

+0

Bu cevap için de teşekkürler. Bana biraz zaman harcayacak ve clojure ve lisp tip programlamaya yeni başladığımdan beri ne yaptığımı basitleştirip basitleştiremeyeceğimi göreceğim. Bazen ne yapmak istediğimi biliyorum ama ne çağrıldığını bilmiyorum ve iyi bir arama terimim olduğunda bile, clojure için sonuçlar çok sınırlı. Sadece yapmaya çalıştığım şeyin "oto-currying" olarak adlandırılabileceğini öğrenmek büyük bir yardımdır. – dansalmo

İlgili konular