lassen vs def in clojure
Frage
Ich mag eine lokale Instanz einer Java Scanner
Klasse in einem clojure Programm machen. Warum funktioniert das nicht:
; gives me: count not supported on this type: Symbol
(let s (new Scanner "a b c"))
, aber es lässt mich eine globale Instanz wie folgt erstellen:
(def s (new Scanner "a b c"))
Ich hatte den Eindruck, dass der einzige Unterschied war, Umfang, aber anscheinend nicht. Was ist der Unterschied zwischen let
und def
?
Lösung
Das Problem ist, dass die Nutzung von let
falsch ist.
Lassen Sie funktioniert wie folgt:
(let [identifier (expr)])
So Ihr Beispiel so etwas wie dies sein sollte:
(let [s (Scanner. "a b c")]
(exprs))
Sie können nur die lexikalischen Bindungen im Rahmen von let let gemacht verwenden (das Öffnen und Schließen Pars). Lassen Sie schafft nur eine Reihe von lexikalischen Bindungen. Ich benutze def eine globale Bindung für die Herstellung und lasse für die Bindung etwas, das ich nur im Rahmen der Let will, wie es Dinge sauber hält. Sie haben beide ihre Verwendung.
. HINWEIS: (. Klasse) ist das gleiche wie (neue Klasse), es ist nur syntaktischer Zucker
Andere Tipps
LET ist nicht „im aktuellen Bereich eine lexikalische Bindung machen“, sondern „einen neuen lexikalischen Gültigkeitsbereich mit den folgenden Bindungen machen“.
(let [s (foo whatever)] ;; s is bound here ) ;; but not here
(def s (foo whatever)) ;; s is bound here
Die korrekte Syntax:
(let [s (Scanner. "a b c")] ...)
Vereinfacht:. def für globale Konstanten ist, lassen ist für lokale Variablen
Die Syntax für sie ist anders, auch wenn die Bedeutung beziehen.
let nimmt eine Liste der Bindungen (Name Wertepaare), gefolgt von Ausdrücken im Rahmen derer zu bewerten verbindlich.
def dauert nur eine Bindung, keine Liste, und fügt sie den globalen Kontext.
let
als syntaktischen Zucker Sie könnten einen neuen lexikalischen Gültigkeitsbereich mit fn
dann für die Erstellung der Anwendung sofort:
(let [a 3 b 7] (* a b)) ; 21
; vs.
((fn [a b] (* a b)) 3 7) ; 21
So Sie let
mit einem einfachen Makro und fn
implementieren könnte:
(defmacro fnlet [bindings & body]
((fn [pairs]
`((fn [~@(map first pairs)] ~@body) ~@(map last pairs)))
(partition 2 bindings)))
(fnlet [a 3 b 7] (* a b)) ; 21