作为一个侧面项目,我正在为图像合成创建一个Clojure DSL(clisk)。
我对功能命名的最佳方法不太感兴趣,我在DSL中具有类似于Clojure核心中的功能的功能,例如我的DSL中需要+
功能或类似功能附加地组合图像/执行矢量数学运算。
据我所知,有几个选择:
+
)。在DSL代码中看起来不错,但会覆盖clojure.core版本,这可能会导致问题。人们可能会感到困惑。my-ns/+
)。避免冲突,但为方便起见,阻止人们use
命名空间,看起来有点难看。v+
)。可以use
轻松地避免冲突,但这个名字有点难看,可能难以记住。vector-add
)。详细但描述性,没有冲突。clojure.core/+
并使用多方法+
重新定义(正如georgek建议的那样)。 示例代码可能类似于:
(show (v+ [0.9 0.6 0.3]
(dot [0.2 0.2 0]
(vgradient (vseamless 1.0 plasma) ))))
最佳/最惯用的方法是什么?
答案 0 :(得分:4)
首先,在中缀表达式中重复出现运算符需要一个很好的语法,但对于带有前缀语法的lisp,我认为这并不重要。因此,让用户为显式命名空间键入更多字符并不是一种犯罪行为。而clojure对命名空间和别名有很好的支持。所以用户很容易选择自己的短前缀:例如(x/+ ...)
。
第二,看reader docs,没有很多非字母数字符号可供使用,所以像:+
这样的东西就出来了。所以没有“可爱”的解决方案 - 如果你选择一个前缀,它必须是一个字母。这意味着像x+
这样的东西 - 让用户选择一个别名更好,价格还要多一个字符,并且x/+
。
所以我想说:忽略核心,但期望用户(:require .... :as ...)
。如果他们非常喜欢你的包,他们希望它是默认的,那么他们可以(:use ...)
并明确地处理核心。但是你选择运营商的前缀似乎是一个糟糕的妥协。
(我认为我没见过任何使用单字母前缀的库。)
另一种可能性是提供上述和还一个单独的包,其中包含长名称而不是运算符(只是简单地定义为匹配原始包中的值)。然后,如果人们想要(:use ...)
但想要避免冲突,他们可以使用它(但真正的(vector-add ...)
优于(vector/+ ...)
的优势是什么?)
最后我会检查+
是如何实现的,因为如果已经涉及某种类型的调度,那么georgek的评论很有意义。
(上面的“运算符”我只是指单字符,非字母数字符号)