rhlvora
rhlvora

Reputation: 47

Why isn't this clojure function executing?

I'm working through some clojure examples from braveclojure:

http://www.braveclojure.com/writing-macros/

Currently I am trying to execute this

(ns turtle (:use clojure.pprint))

(def criticisms {:good "good code:" :bad "bad code:"})

(defn criticize-code
    [[critkey code]]
    `(println (~critkey criticisms) (quote ~code)))

(defmacro code-critic
    [code-evaluations]
    `(do ~@(map criticize-code code-evaluations)))

(println "executed code critic")
(code-critic {:good (+ 1 1) :bad (1 + 1)})
(println "code critic expansion")
(pprint (macroexpand '(code-critic {:good (+ 1 1) :bad (1 + 1)})))

;why isn't this executing?
(println "criticize code expansion")
(criticize-code [:good '(+ 1 1)])

Basically, I can verify that criticize-code returns properly formatted code through println; but I cannot actually execute it...can someone please tell me what I'm doing wrong?

Thank you!

Upvotes: 2

Views: 100

Answers (1)

A. Webb
A. Webb

Reputation: 26446

The function criticize-code is being invoked. The quasi-quote, `, in the body of the function is a reader macro for syntax-quote, which means the following println form, after its trip through the syntax-quote reader, will be returned as data structure rather than executed. The criticize-code function is semantically equivalent to

(defn criticize-code
  [[critkey code]]
  (list 
    'clojure.core/println 
    (list critkey 'turtle/criticisms) 
    (list 'quote code)))

If you want to treat the resulting data structure as code at the REPL, you can eval it directly.

turtle=> (criticize-code [:good '(+ 1 1)])
(clojure.core/println (:good turtle/criticisms) (quote (+ 1 1)))
turtle=> (eval (criticize-code [:good '(+ 1 1)]))
good code: (+ 1 1)
nil

So why would you want a function that works like this? As a helper to a macro, as here for code-critic. Macros deal with code-as-data-as-code. Therefore, if you stick in a helper function at the as-data stage, it will need to return its result as data. Otherwise, the code you want to be compiled is just executed at "compile" time with its return value (println returns nil) compiled instead.

Upvotes: 3

Related Questions