什么是Clojure和F#的DSL创建工具?

时间:2012-06-01 07:50:14

标签: f# clojure metaprogramming dsl

我正在尝试确定Clojure和F#用于创建DSL的设施。每个提供什么设施来创建和操纵DSL?

由于F#是静态类型的,这是否会使这项特定任务更加困难?在Clojure部分,我没有真正的经验,但已知所有LISP都非常适合元编程/ DSL。

我的问题不是打算在两种语言之间发动战争。如果我最近对这两个问题提出质疑是因为我认为两者都很棒并且想要更多地了解这两者的具体情况。

在阅读了一些关于故意编程的日子之后,它让我重振了我对DSL和所有人的兴趣。

虽然我对F#有一些了解,但我还没有使用引文或类似的东西开发任何东西。我已经看到了基于歧视联盟的DSL的例子,这看起来很有趣。

2 个答案:

答案 0 :(得分:5)

您最终可以使用任何语言创建DSL。

使Clojure /其他Lisps特别独特且非常适合元编程的原因是它们是homoiconic - 也就是说,语言本身在同一语言的数据结构中自然表达。在Lisp中,您实际上是直接将代码编写为AST

这非常强大 - 这意味着代码生成实际上等同于创建相对简单的数据结构。该语言为您提供了在编译时通过宏生成任意代码的工具。这有效地允许您“扩展语言”以支持您需要的任何特定DSL。

作为一个例子,我最近发现自己想要在Clojure中使用命令式for循环(对函数式编程纯粹主义者道歉,但有时你想要一个......)。将此添加到该语言是一个5线:

(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#)))

现在我可以做到:

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

这显然是一个简单的例子,但是应该清楚的是,通过创建一组扩展到您想要的代码的短宏来生成新语言结构的能力使得构建DSL特别容易。

您可能会感兴趣的一些阅读/链接:

答案 1 :(得分:4)

我不能谈论Clojure,因为我还没有使用它,但我对F#中的DSL有所了解。 F#提供了两种主要的面向语言的编程功能(Don Syme喜欢称之为):代码引用和计算表达式。

代码引用更接近于像Lisp这样的语言中的宏。它们允许您以编程方式生成表达式,然后可以执行它们。通过在F#表达式上使用ReflectedDefinition属性,您可以访问其AST。有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/dd233212.aspx

计算表达式类似于Haskell中的符号。编译器使用特殊语法将代码重写为对您定义的类型的调用。理想情况下,这种类型应该形成一个单子。由于它们是伪装的monad,因此它们应该允许您实现DSL的自定义语义。有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/dd233182.aspx

IMO计算表达式更适合在F#之上编写DSL,而代码引用更适合转换或翻译等任务(例如F#到JavaScript)。

除了这两个主要功能外,您还可以使用其他语言。

当然,上面我一直只讨论嵌入式域特定语言。您可以加倍努力,使用fslex和fsyacc作为独立的DSL。