What are the DSL creation tools for Clojure and F #?

I am trying to determine what tools Clojure and F # have for creating DSL. What tools does each provide to create and manage DSL?

With F # static input, does this make this specific task difficult? I have no real experience on the Clojure part, but all LISPs are known to be great for metaprogramming / DSL.

My question is not for war or anything similar between both languages. If I ask questions about what has been happening lately, it is because I think both of them are great and want to know more about the specifics of the two.

After reading a few days about intentional programming, he made me revive my interest in DSL and all.

Although I have some knowledge of F #, it’s true, I have not developed anything yet using quotes or something like that. I have seen examples of DSLs based on discriminatory unions that seem interesting.

+6
source share
2 answers

Ultimately, you can create DSL in any language.

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

This is surprisingly powerful β€” meaning that code generation is actually equivalent to creating a relatively simple data structure. And the language provides the ability to generate arbitrary code at compile time using macros. This effectively allows you to "expand the language" to support any specific DSL that you need.

As an example, I recently discovered that I wanted an imperative for loop in Clojure (apologies for functional programming purifiers, but sometimes you need 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 hopefully it will be clear that the ability to generate new language constructs by creating a set of short macros that extend to exactly the code you want makes DSL creation especially easy.

Some reads / links that may interest you:

+5
source

I can’t talk about Clojure since I haven’t used it, but I know a little about DSL in F #. F # provides two main functions oriented to a programming language (which they like Don Syme): code quotes and expressions of calculations.

Code quotes are closer to what you would get with macros in a language such as Lisp. They allow you to create programmatic expressions that you can then execute. Using the ReflectedDefinition attribute in F # expressions, you gain access to your AST. See http://msdn.microsoft.com/en-us/library/dd233212.aspx for more details.

Expression calculations are similar to notations in Haskell. The compiler rewrites the code using special syntax into calls of the type you define. This type should ideally form a monad. Since they are hidden in monads, they should allow you to implement the custom semantics of your DSL. See http://msdn.microsoft.com/en-us/library/dd233182.aspx for more details.

IMO calculations are better for writing DSL on top of F #, while code citations are better for tasks such as conversions or translations (like F # in JavaScript).

In addition to these two basic functions, you have the rest of the language that you can use.

Of course, above I talked only about built-in domains. You can go the extra mile and use fslex and fsyacc for standalone DSL.

+4
source

Source: https://habr.com/ru/post/917156/


All Articles