2012-12-21 29 views
6

znalazłem następujący kod (w this blog post że rozwiązuje Coin Changer Kata):Proszę wyjaśnić mi następujący kod Clojure

(defn change-for [amount] 
    (let [denominations [25 10 5 1] 
     amounts (reductions #(rem %1 %2) amount denominations) 
     coins (map #(int (/ %1 %2)) amounts denominations)] 
    (mapcat #(take %1 (repeat %2)) coins denominations))) 

Część znajdę trudno jest: (reductions #(rem %1 %2) amount denominations).

Jak się dowiedziałem, reductions właśnie oblicza wynikową kolekcję przyrostowo w oparciu o jakąś daną funkcję. Przykład: (reductions + [1 2 3]) podaje [1 3 6].

1   ; first element 
1 + 2  ; second element 
1 + 2 + 3 ; third element 

Kolejna funkcja rem który oblicza pozostała część jest nadal bardzo prosty do zrozumienia.

Aby zrozumieć resztę kodu próbowałem następujące:

; first try, to see if this call works 
; outside the original code (the change-for function) 
(reductions #(rem %1 %2) 17 [10 5 1]) ; --> [17 7 2 0] 

; tried to use the reductions which takes only one argument 
; notice that 17 is now inside the array 
(reductions #(rem %1 %2) [17 10 5 1]) ; --> [17 7 2 0] 

; further simplified the expression 
(reductions rem [17 10 5 1]) ; --> [17 7 2 0] 

Ostatnim krokiem było usunięcie funkcji anonimowy, jak to opisano w this blog post.

W tym momencie sytuacja staje się zagmatwana (przynajmniej dla mnie): rem przyjmuje 2 argumenty i nie rozumiem, jak są stosowane podczas korzystania z tablicy [17 10 5 1]. Próbowałem następujące połączenia:

(rem [17 10 5 1]) ; --> gives error 
(rem [17 10 5 1] [17 10 5 1]) ; --> also gives error 
(rem 17 10) ; --> works, but how do you use it with collections? 

Może ktoś mi wyjaśnić, jak to rem funkcja działa z funkcją reductions?

Inną rzeczą, ja nie bardzo rozumiem to: jak są te argumenty procentowe stosowane (w #(rem %1 %2))? Mam na myśli skąd pochodzą? Próbowałem wywoływać rem w następujący sposób, ale pojawia się błąd: (#(rem %1 %2) 17 [10 5 1]). Musi być coś, co funkcja reductions wykonuje za kulisami, aby to działało, prawda?

Początkowo myślałem, że #(rem %1 %2) był zestawem. Te deklarowane są w podobny sposób jak zestawy i może być łatwo nadużywana (przez kogoś dopiero zaczynasz z Clojure):

(type #{1 2 3}) ; --> clojure.lang.PersistentHashSet 
(type #(1 2 3)) ; --> user$eval12687$fn__12688 

Czy ktoś może wskazać mi na miejscu/książki/cokolwiek to wyjaśnia sztuczek Clojure takich jak "Specjalny formularz do anonimowej funkcji"? Większość zasobów daje najprostsze konstrukcje (te, które są podobne do wszystkich innych pochodnych lispów) bez wchodzenia w zawiłości Clojure. Znalazłem a site, który wygląda całkiem nieźle (a także wyjaśnia anonimowe funkcje, o których wspomniałem powyżej). Jakieś inne takie zasoby?

Odpowiedz

5

to:

(reductions #(rem %1 %2) amount denominations) 

odpowiada to:

(reductions rem amount denominations) 

i jak zauważyli

(reductions function start collection) 

zwraca sekwencji pośrednich wyników zmniejszenie collection z function (biorąc start jako f irst argument pierwszego etapu redukcji). function musi przyjmować dwa parametry.

Więc wynik:

(reductions function start [1 2 3 4 5]) 

jest

((function start 1) (function (function start 1) 2) ...) 

Składnia #(rem %1 %2) jest tylko skrótem do definiowania anonimową funkcję, która pobiera dwa parametry (%1 i %2), wzywa rem na nich i zwraca wynik.

To odpowiednik:

(fn [a b] (rem a b)) 
Powiązane problemy