2017-01-09 5 views
0

Ich erkunde Makros mit grundlegenden Beispielen und ich verstehe nicht, wie es funktioniert. DieseClojure: Warum funktioniert dieses Makro nicht?

:

(defmacro evalf [f v] 
    (f v)) 
(evalf + 2) 

funktioniert nicht.

Ich habe versucht:

(defmacro evalf [f v] 
    '(f v)) 
(evalf + 2) 

kein Glück ...

Ich verstehe nicht andere Schreibweisen: ~ ~ @ und so weiter, aber sie funktioniert auch nicht. Ich sehe, dass Symbol f nicht auf + zeigt, aber ich weiß nicht zu sagen "nimm den Wert von f, was + ist".

Können Sie es klarer machen? Vielen Dank im Voraus

Antwort

4

Je nachdem, was Sie wollen, Sie dort zu tun gibt zwei Varianten:

Zuerst ein (die Sie wahrscheinlich wollen) ist:

(defmacro evalf [f v] `(~f ~v)) 

oder

(defmacro evalf [f v] (list f v)) 

Beide tun das gleiche: erzeugen Sie den s-Ausdruck, den Sie brauchen. Mit diesem würde (evalf + 10) in Kompilierzeit zu (+ 10) erweitert und dann in Laufzeit erfolgreich ausgewertet werden.

zweite ist dies:

(defmacro evalf [f v] ((resolve f) v)) 

Nun wird die Funktion f würde zur Compile-Zeit aufgerufen werden, so würde Makro auf das Ergebnis erweitert werden: 10

Ihre Variante mit (f v) gescheitert still , denn wenn Sie (evalf + 10) anrufen, die + hier ist nur ein einfaches Symbol, kein Verweis auf die Funktion aus der Sicht des Makros, so versucht esaufrufen, da das Symbol in clojure die Semantik der Funktion hat, ist es völlig korrekte Syntax, aber dieser Aufruf erzeugt nil. (Das Beispiel des Symbolaufrufs: ('+ {'+ 10}) => 10) Wenn Sie also die Funktion, benannt als dieses Symbol, erhalten wollen, müssen Sie sie wie in meinem zweiten Beispiel lösen.

Und die Variante mit '(f v) erweitert gerade in die Liste der zwei Symbole: 'f und 'v, und führt dann zur Laufzeit Anruf ('f 'v), die auch nil zurückgibt, wie die erste Variante.

+0

Danke, beide sind Antworten, aber ich habe mehr deins verstanden, also habe ich das gewählt –

4

(defmacro evalf [f v] 
    (list f v)) 

(evalf (partial * 2) 66); 132 

Im Aufruf von evalf

  • Versuchen Sie, die Argumente übergeben unevaluierten als Formen(partial * 2) und 66;
  • der Körper des Makros ergibt den Ausdruck(list '(partial * 2) '66);
    • , die an die Form ((partial * 2) 66)
    • auswertet, die vom Makro zurückgegeben, auswertet, um 132.

Eine alternative Syntax zitiert, ist

(defmacro evalf [f v] 
    `(~f ~v))