Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the DSL Creation Facilities for Clojure and F#? [closed]

I am trying to determine what facilities Clojure and F# have for creating DSLs. What facilities does each provide in order to create and manipulate DSLs?

As F# is statically typed, does this make it more difficult for this specific task? On the Clojure part I have no real experience but all LISPs are known to be great for metaprogramming/DSLs.

My question is not intended to make a war or something of the sort between both languages. If I'm making questions about the both lately is because I do think both are great and want to know more about the specifics of the two.

After reading some days about Intentional Programming, it has made me revive my interest in DSLs and all.

Although I have some knowledge of F# it's true I haven't yet developed anything using quotations or something like that. I've seen examples of DSLs based on discriminated unions which seem interesting.

like image 264
Jacobo Polavieja Avatar asked Jun 01 '12 07:06

Jacobo Polavieja


1 Answers

You can ultimately create DSLs in any language.

What make Clojure / other Lisps particularly unique and well-suited to metaprogramming is that they are homoiconic - that is, the language itself is expressed naturally in the data structures of the same language. In Lisp, you are effectively writing code directly as an AST.

This is surprisingly powerful - it means that code generation is effectively equivalent to creating a relatively simple data structure. And the language provides facilities for you to generate arbitrary code at compile time via macros. This effectively allows you to "extend the language" to support any particular DSL you require.

As an example, I recently found myself wanting an imperative for loop in Clojure (apologies to functional programming purists, but sometimes you want one....). Adding this to the language was a 5-liner:

(defmacro for-loop [[sym init check change :as params] & steps]
  `(loop [~sym ~init value# nil]
     (if ~check
       (let [new-value# (do ~@steps)] (recur ~change new-value#))
       value#)))

So now I can do:

(for-loop [i 0 (< i 10) (inc i)]
   (println i))
=> < prints numbers from 0..9 >

This is obviously a simple example, but it should hopefully be clear that the ability to generate new language constructs by creating a set of short macros that expand to exactly the code you want makes building a DSL particularly easy.

Some reading / links you may find interesting:

  • The Curious Clojureist - Excellent video describing some of the unique features of Clojure (with some amusing comparisons to Java)
  • Paul Graham - Beating the Averages
  • What makes lisp macros so special
like image 189
mikera Avatar answered Oct 20 '22 16:10

mikera