避免在Clojure DSL中发生名称冲突

时间:2012-07-23 07:32:18

标签: clojure namespaces dsl

作为一个侧面项目,我正在为图像合成创建一个Clojure DSL(clisk)。

我对功能命名的最佳方法不太感兴趣,我在DSL中具有类似于Clojure核心中的功能的功能,例如我的DSL中需要+功能或类似功能附加地组合图像/执行矢量数学运算。

据我所知,有几个选择:

  1. 在我自己的命名空间中使用相同的名称(+)。在DSL代码中看起来不错,但会覆盖clojure.core版本,这可能会导致问题。人们可能会感到困惑。
  2. 使用相同的名称,但要求其合格(my-ns/+)。避免冲突,但为方便起见,阻止人们use命名空间,看起来有点难看。
  3. 使用其他短名称,例如(v+)。可以use轻松地避免冲突,但这个名字有点难看,可能难以记住。
  4. 使用其他长名称,例如(vector-add)。详细但描述性,没有冲突。
  5. 排除clojure.core/+并使用多方法+重新定义(正如georgek建议的那样)。
  6. 示例代码可能类似于:

     (show  (v+ [0.9 0.6 0.3] 
                 (dot [0.2 0.2 0] 
                      (vgradient (vseamless 1.0 plasma) ))))
    

    最佳/最惯用的方法是什么?

1 个答案:

答案 0 :(得分:4)

首先,在中缀表达式中重复出现运算符需要一个很好的语法,但对于带有前缀语法的lisp,我认为这并不重要。因此,让用户为显式命名空间键入更多字符并不是一种犯罪行为。而clojure对命名空间和别名有很好的支持。所以用户很容易选择自己的短前缀:例如(x/+ ...)

第二,看reader docs,没有很多非字母数字符号可供使用,所以像:+这样的东西就出来了。所以没有“可爱”的解决方案 - 如果你选择一个前缀,它必须是一个字母。这意味着像x+这样的东西 - 让用户选择一个别名更好,价格还要多一个字符,并且x/+

所以我想说:忽略核心,但期望用户(:require .... :as ...)。如果他们非常喜欢你的包,他们希望它是默认的,那么他们可以(:use ...)并明确地处理核心。但是你选择运营商的前缀似乎是一个糟糕的妥协。

(我认为我没见过任何使用单字母前缀的库。)

另一种可能性是提供上述和一个单独的包,其中包含长名称而不是运算符(只是简单地定义为匹配原始包中的值)。然后,如果人们想要(:use ...)但想要避免冲突,他们可以使用它(但真正的(vector-add ...)优于(vector/+ ...)的优势是什么?)

最后我会检查+是如何实现的,因为如果已经涉及某种类型的调度,那么georgek的评论很有意义。

(上面的“运算符”我只是指单字符,非字母数字符号)