如何在没有括号的情况下在Clojure(脚本)中编写DSL?

时间:2016-10-11 22:52:19

标签: clojure racket dsl clojurescript

由于Clojure(Script)是一个Lisp,所有DSL(Domain Specific Languages)的例子都使用括号来编码表达式begin和end(就像Lisp那样)。然而,至少另一种Lisp方言(Racket)有很多例子,而且#34;括号少了#34; DSL(Creating Languages in RacketDSL1DSL2)。我可以使用一些特殊的方法来转换:

if (a > 10) { print "Ok!" }    ==>    (if (> a 10) (print "Ok!"))

我想知道是否有一些最佳实践指南或库在Clojure中进行这些转换。或者也许某人已将Racket的功能移植到Clojure(我不是Racket用户)。 Racket用户可以向我指出一些有关如何处理此类DSL的Racket文档吗?

2 个答案:

答案 0 :(得分:6)

Clojure故意没有添加用户可定义的阅读器宏。这是用于执行顶级代码转换的功能。 Clojure确实包括这些,它们不是用户可定义的,因此它们有固定数量。

一个例子是#_ reader宏,它完全删除了下一个表达式。 (你可以堆叠它们)

#_#_#_(:println  1) (println 2) (println 3) (println 4)
4

您可以做的是定义标记文字,它解决了许多相同的问题,尽管它们并非真正用于定义外部DSL。大多数情况下,您将拥有顶级dsl-start宏,然后您不必在开始符号周围的初始两个之外使用任何()。有限制,您在语言中提供的内容必须包含可读表达式(符号,地图,矢量,列表等)

(with-my-special-language
   if (a > 10) { print "Ok!" }
   if (a > 42) { print "Even Better!" }
)

如果您真的想避免将两个()暴露给编写此代码的人,您可以将该代码读入字符串,添加()您的自我,然后对其进行评估。这样直接访问读者非常方便。

答案 1 :(得分:1)

There is a library called chiara which lets you write Clojure without using parentheses. From the README:

(ns my-ns
  (use chiara))

(use-chiara) (chiara

defn foo [x]
  map inc (range x)

def my-list
  foo 10

)

It introduces syntax macros which let you do the kind of transformations you're after.