2012-08-14 10 views
23

Ich lerne über Clojure Makros, und die Codebeispiele haben manchmal die Konstrukte '~symbol oder alternativ ~'symbol. Ich weiß, dass (quote und ' verhindern, dass ein Formular ausgewertet wird, und dass die Backquote zusätzlich die Namespace-Qualifizierung hinzufügt, und dass ~ die Auswertung eines zitierten Formulars bewirkt. Meine Frage ist: Warum ist es sinnvoll zu stoppen und dann mit der Bewertung zu beginnen? Ich nehme auch an, dass ~'symbol und '~symbol unterschiedlich sind, aber wie?Was ist der Zweck von ~ 'oder' ~ in Clojure?

Antwort

30

~'symbol wird verwendet, um ein unqualifiziertes Symbol zu produzieren. Clojure-Makros erfassen den Namespace standardmäßig, sodass ein Symbol in einem Makro normalerweise in (your-namespace/symbol) aufgelöst wird. Das Unquote-Zitat-Idiom führt direkt zu dem einfachen, nicht qualifizierten Symbolnamen - (symbol) - durch Auswerten zu einem zitierten Symbol. Von der Freude über Clojure:

(defmacro awhen [expr & body] 
    `(let [~'it ~expr] ; refer to the expression as "it" inside the body 
    (when ~'it 
     (do [email protected])))) 

(awhen [:a :b :c] (second it)) ; :b 

'~symbol wird wahrscheinlich ähnlich, um einen Namen in dem Makro oder etwas verwendet. Hier wird symbol an einen Wert gebunden - let [symbol 'my-symbol]. Dieser Wert wird dann in den Code eingefügt, den das Makro erzeugt, indem er symbol auswertet.

+0

:) Danke, das macht Sinn. – Alex

+0

gibt es noch einen Punkt, der mir unklar bleibt: '(unquote (quote user/foo))' ergibt 'foo' anstelle von' user/foo', wann und wie kommt es vor, dass der Namespace entfernt wird? Wie steht es mit dem "normalen" Verhalten von "unquote", das die folgende Form auswertet? – skuro

+1

Das erste Beispiel funktioniert nicht. Es sollte '\ 'sein (lassen Sie [~' es ~ Ausdruck] ...' – Ming

4

~ ist ein Leser Makro für die unquote Funktion. innerhalb einer angegebenen Liste verursacht es ein Symbol eher dann als wörtliches Symbol

user> (def unquoted 4) 
user>`(this is an ~unquoted list) 
(user/this user/is user/an 4 clojure.core/list) 
user> 

alles außer dem nur als Symbol wurde verwendet unquoted Symbol verwendet wird, bewertet werden, in dem nicht notiert, um seinen Wert von 4. diesem aufgelöst wurde, ist meist oft beim Schreiben von Makros verwendet. Der Repl druckt auch den Namespace (Benutzer) vor den Namen, wenn er die resultierende Liste druckt.

viele Makros, sind im Grunde nur Vorlagen, die entworfen sind, um eine Reihe von leichten Variationen an etwas zu tun, was in einer Funktion nicht möglich ist. In diesem erfundenen Beispiel definiert ein Vorlagenmakro eine Funktion, indem es einen Aufruf von def erzeugt. Syntax-Zitat mit unquoting macht dies viel einfacher zu lesen:

user> (defmacro def-map-reducer [name mapper reducer] 
     `(defn ~name [& args#] 
       (reduce ~reducer (map ~mapper args#)))) 

#'user/def-map-reducer 
user> (def-map-reducer add-incs inc +) 
#'user/add-incs 
user> (add-incs 1 2 3 4 5) 
20 

im Vergleich zu:

user> (defmacro def-map-reducer [name mapper reducer] 
      (let [args-name (gensym)] 
       (list `defn name [`& args-name] 
        (list `reduce reducer (list `map mapper args-name))))) 

#'user/def-map-reducer 
user> (def-map-reducer add-decs dec +) 
#'user/add-decs 
user> (add-decs 1 2 3 4 5) 
10 
user> 

im zweiten Beispiel, das ich nicht auch die Auto-gensyms-Funktion verwenden, weil ich nicht in Ein Syntax-Zitat

+0

Also ich weiß, warum ich ~ vor einem Symbol in einer Liste, die ich zuvor zitiert hatte, verwenden möchte, meine Frage ist speziell, warum ich ~ 'oder' ~ direkt neben einander verwenden würde. – Alex

+0

hoffentlich zeigt dieses Beispiel die Motivation besser, danke für das Feedback :) –