There is two way to make a domain-specific language with a clojure back-end
:
- if you want the language to be an extension of Clojure, still to be used
in a REPL or by clojure source
   -----> you write macros. That's what I call embedded.  There is a lot of
litterature on Embedded Domain Specific Language in functional languages. (A
*lot* in Haskell, for example)
In this situation, eval is most of the time evil.

- you want to read instructions that are very far from Clojure in a file and
execute them. (Your case, not by choice but because of the ICFP  specs).
Then, eval is necessary. But you have to call it only once per compiled
function, ideally, and never while executing the code (for performance).
In your situation, I would write
(defn compile-instruction [instructions] ...)

Then, when reading the instructions
(let [compiled-function (eval (compile-instruction (read-file...)))]
 ...

Then, eval is called once, just after reading and compiling. And
compiled-function is a real Clojure function.

Have fun,

Nicolas.







On Sat, Jun 19, 2010 at 3:39 AM, Eugen Dück <eu...@dueck.org> wrote:

> Thanks Nicolas,
>
> your first variant resembles the generated code much closer than my
> initial approach, which is great. I need the eval though, to be able
> to pass in non literals. In my real program I'm reading the
> instructions from a binary file. So if I want to be able to do
> something like this:
>
> (def three-instructions '([+ 2 3] [- 0 1] [+ 1 0]))
> (def compiled (compile-instructions three-instructions))
>
> The macro would have to look like this:
>
> (defmacro compile-instructions
>  [instructions]
>  (let [memory (gensym "memory-")]
>   `(fn [~memory]
>          ~@(map (fn [[op m1 m2]]
>                 `(aset ~memory ~m1 (~op (aget ~memory ~m1) (aget
> ~memory ~m2))))
>                (eval instructions)))))
>
> But I like your suggestion to turn it into a function even better:
>
> (defn compile-instructions
>  [instructions]
>  (let [memory (gensym "memory-")]
>    (eval
>     `(fn [~memory]
>       ~@(map (fn [[op m1 m2]]
>                `(aset ~memory ~m1 (~op (aget ~memory ~m1) (aget ~memory
> ~m2))))
>               instructions)))))
>
> And
>
> (def compiled (compile-instructions three-instructions)))
>
> just works as before. So I guess macros don't add any value here.
>
> > eval is evil, but eval is not evil is a compiler (you have to evaluate
> the
> > code you read).
> > However eval is evil again in an "embedded compiler", when you use macro
> to
> > extend Clojure.
>
> What do you mean by "embedded compiler"?
>
> Eugen
>
> --
> 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<clojure%2bunsubscr...@googlegroups.com>
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
>

-- 
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