2012-12-21 9 views
6

ich den folgenden Code gefunden (in this blog post, die die Coin Changer Kata löst):Bitte erläutern Sie mir folgende Clojure Code

(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))) 

Der Teil finde ich schwierig ist: (reductions #(rem %1 %2) amount denominations).

Wie ich herausgefunden habe, berechnet reductions nur die resultierende Sammlung inkrementell basierend auf einer bestimmten Funktion. Beispiel: (reductions + [1 2 3]) ergibt [1 3 6].

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

Die nächste Funktion, rem, die den Rest berechnet ist nach wie vor extrem einfach zu verstehen.

Um den Rest des Codes verstehe ich folgendes versucht:

; 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] 

Der letzte Schritt, um die anonyme Funktion in this blog post wie beschrieben zu entfernen war.

Hier werden die Dinge verwirrend (zumindest für mich): rem dauert 2 Argumente und ich verstehe es nicht, wie sie angewendet werden, wenn Sie das Array [17 10 5 1] verwenden. Ich habe versucht, die folgenden Aufrufe:

(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? 

Kann jemand mir erklären, wie diese rem Funktion mit der reductions Funktion funktioniert?

Eine andere Sache, die ich nicht ganz verstehe ist: Wie werden diese Argumente Prozent angewendet (in #(rem %1 %2))? Ich meine, woher kommen sie? Ich versuchte rem auf die folgende Weise zu benennen, aber ich erhalte einen Fehler: (#(rem %1 %2) 17 [10 5 1]). Es muss etwas geben, das die reductions Funktion hinter den Kulissen tut, um diese Arbeit zu machen, richtig?

Zuerst dachte ich, dass #(rem %1 %2) ein Set war. Diese werden in ähnlicher Weise wie Sätze erklärt und leicht missbraucht werden kann (von jemand gerade erst anfangen mit Clojure):

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

Kann jemand zeigen Sie mir auf eine Website/Buch/was auch immer das erklärt Clojure Tricks wie "Die spezielle Form für eine anonyme Funktion"? Die meisten Ressourcen geben nur die einfachsten Konstrukte (die ähnlich zu allen anderen Lisp-Derivaten sind), ohne auf die Feinheiten von Clojure einzugehen. Ich fand a site, die ziemlich gut aussieht (und erklärt auch die anonymen Funktionen, die ich oben erwähnte). Irgendwelche anderen Ressourcen?

Antwort

5

Dieses:

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

entspricht dies:

(reductions rem amount denominations) 

und wie Sie

bemerkt
(reductions function start collection) 

gibt eine Sequenz von Zwischenergebnisse der collection mit function reduziert (Nehmen start als die f erstes Argument des ersten Reduktionsschrittes). function muss zwei Parameter annehmen.

So das Ergebnis:

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

ist

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

Die #(rem %1 %2) Syntax ist nur eine Abkürzung für anonyme Funktion definiert, die zwei Parameter (%1 und %2) hat, ruft rem auf sie und gibt das Ergebnis zurück.

Es ist äquivalent zu:

(fn [a b] (rem a b)) 
Verwandte Themen