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