2013-10-17 47 views
6

Bu işlev oluşturucuyu, P.Graham'ın "ANSI Common Lisp" (sayfa 110) bölümünde gerçekleştirmesi için buluyoruz. Argümanlar n> 0 alıntılanan fonksiyon isimleridir. Tamamen bunu anlamıyorum, bu yüzden bunun altında sorularımı kodu buraya alıntı ve belirtirsiniz:(derleme)

(defun compose (&rest fns) 
    (destructuring-bind (fn1 . rest) (reverse fns) 
    #'(lambda (&rest args) 
     (reduce #'(lambda (v f) (funcall f v)) 
       rest 
       :initial-value (apply fn1 args))))) 

oluşturmak için argüman listesi ters ve (şimdi ilk) eleman fn1' bağlı, ambalajsız edilir 've geri kalan' dinlenmek '. En dıştaki lambda'nın gövdesi, bir azaltmadır: (funcall fi (funcall fi-1 ...)), ilkini geri yüklemek için ters sırayla işlenenler.

1) En dıştaki lambda ifadesinin rolü nedir? Yani, 'args' nereden geliyor? Yıkım-bağlama ilk argümanı olarak belirtilen veri yapısı mı? 2) En içteki lambda iki argümanı nereden alır?

Kodun ne yaptığını anlayabiliyorum ama yine de sözcük kapsamı benim için bir gizem. Her türlü ve tüm yorumları sabırsızlıkla bekliyoruz! peşin sayesinde // Marco

+0

olabilir? – Marcin

+1

Özür dilerim, bu konuyu http://stackoverflow.com/questions/5928106/compose-example-in-paul-grahams-ansi-common-lisp – ocramz

+0

@Marcin adresinde görmedim;) Kötü bir uygulama mı? Hala bir noob değilim – ocramz

cevap

10

Muhtemelen daha kolay Son işlev ve diğerlerinin tümünü ters sırayla zincirleme sonucu son fonksiyondan geldi.

Not: compose1 daha basit olarak (defun compose1 (a) a) olarak tanımlanabilir.

bir miktar eşdeğer fakat daha az verimli versiyon Neden tüm asılı parantez

(defun compose (&rest functions) 
    (if (= (length functions) 1) 
     (car functions) 
     (lambda (&rest args) 
     (funcall (first functions) 
       (apply (apply #'compose (rest functions)) 
         args))))) 
+0

Örnekler ve açıklama için teşekkür ederim, bu kesinlikle konuya açıklık getirir! – ocramz

2

1) (birleştirmek ...) sonucu diğer fonksiyonların bileşimini calulates bir işlevdir çünkü dıştaki lambda, sizin için bir kapatma yaratır.

2) En içteki lambda, işlevin azalmasından bağımsızdır. Azaltma, iki argümanın bir fonksiyonunu (en içteki lambda) alır ve bir listeye adım adım uygular, örn. herhangi argüman alan bir fonksiyon, ne onunla yapar uyguluyor:

(defun compose1 (a) 
    (lambda (&rest args) 
    (apply a args))) 

(defun compose2 (a b) 
    (lambda (&rest args) 
    (funcall a (apply b args)))) 

(defun compose3 (a b c) 
    (lambda (&rest args) 
    (funcall a (funcall b (apply c args))))) 

Yani dıştaki lambda dönüş değeri şudur: pratik örnekler ilk birkaç düşünülürse

(reduce #'- '(1 2 3 4)) is (- (- (- 1 2) 3) 4)