由于Clojure(Script)是一个Lisp,所有DSL(Domain Specific Languages)的例子都使用括号来编码表达式begin和end(就像Lisp那样)。然而,至少另一种Lisp方言(Racket)有很多例子,而且#34;括号少了#34; DSL(Creating Languages in Racket,DSL1,DSL2)。我可以使用一些特殊的方法来转换:
if (a > 10) { print "Ok!" } ==> (if (> a 10) (print "Ok!"))
我想知道是否有一些最佳实践指南或库在Clojure中进行这些转换。或者也许某人已将Racket的功能移植到Clojure(我不是Racket用户)。 Racket用户可以向我指出一些有关如何处理此类DSL的Racket文档吗?
答案 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.