After reading Oleg's lecture Typed tagless-final interpretations
( http://okmij.org/ftp/tagless-final/course/ ), I decided to see if
this was possible, or made any sense, to follow this style in
Clojure.

The idea is that, instead of representing a DSL syntax as a data
structure that you interpret, you represent syntax directly as
functions, which dispatch (in the Haskell case, using type classes)
depending on how you want to interpret the expressions. This approach
lets you extend the syntax easily, as well as add new interpreters
easily.  Thus, you can avoid the expression problem when creating your
DSLs.

In Clojure, we can't dispatch on return types, so the best I came up
is https://gist.github.com/782454 which dispatches on a dynamic var
(also attached below). I would have liked to use protocols somehow,
but it's not clear how this could be done. Clearly we have, at compile
time, all the information regarding which specialized method to call
-- we shouldn't have to use slow multimethods. Speed isn't important
in this simple example, but it might become critical if we were to
interpret huge expression trees.

;the gist:  https://gist.github.com/782454

(def *interpreter* nil)
(defmulti lit (fn [i] *interpreter*))
(defmulti neg (fn [i] *interpreter*))
(defmulti add (fn [a b] *interpreter*))

;'eval' instance
(defmethod lit :evaluate [x] x)
(defmethod neg :evaluate [x] (- x))
(defmethod add :evaluate [x y] (+ x y))

;'show' instance
(defmethod lit :show [x] (str x))
(defmethod neg :show [x] (str "(-" x ")"))
(defmethod add :show [x y] (str "(" x " + " y ")"))

(defmacro evaluate [expr]
(binding [*interpreter* :evaluate]
(eval expr)))

(defmacro show [expr]
(binding [*interpreter* :show]
(eval expr)))


;(evaluate (add (lit 3) (neg (lit 2))))
;> 1

;(show (add (lit 3) (neg (lit 2))))
;> "(3 + (-2))"

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to