在Clojure DSL中避免命名冲突

9

作为一个副项目,我正在创建一个关于图像合成的Clojure DSL (clisk)。

在我的DSL中,我有许多与Clojure核心函数相似的函数,例如+函数或类似的函数,用于将图像进行加法合成 / 进行向量数学运算。

就我所见,有几个选择:

  1. 在我的命名空间中使用相同的名称(+)。在DSL代码中看起来不错,但会覆盖clojure.core版本,可能会引起问题。人们可能会感到困惑。
  2. 使用相同的名称,但要求限定作用域(my-ns/+)。避免冲突,但阻止人们方便地使用命名空间,看起来有点丑陋。
  3. 使用不同的简短名称,例如(v+)。可以方便地使用和避免冲突,但名称有点丑陋,可能难以记住。
  4. 使用不同的长名称,例如(vector-add)。冗长但描述性强,无冲突。
  5. 排除clojure.core/+并使用多方法重新定义+(如georgek建议的那样)。

示例代码可能如下所示:

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

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


我不确定我是否正确理解了你的目标,因为难道没有第五个选项,即排除core / +,然后使用多方法重新定义?虽然我猜这会使数字加法变得更慢。 - georgek
1个回答

4
首先,在中缀表达式中操作符的重复出现需要一个良好的语法,但对于具有前缀语法的Lisp来说,我认为这并不那么重要。因此,让用户为显式命名空间输入更多字符并不是什么大问题。Clojure对命名空间和别名有很好的支持,所以用户很容易选择自己的短前缀,例如:(x/+ ...)
其次,查看读取器文档,可以发现没有太多非字母数字符号可供使用,因此像:+这样的东西就不能用了。所以没有“可爱”的解决方案——如果你选择前缀,它必须是一个字母。这意味着类似x+这样的东西——最好让用户选择一个别名,代价是多打一个字符,然后使用x/+
所以我会建议:忽略核心,但期望用户使用(:require .... :as ...)。如果他们非常喜欢你的包,想让它成为默认值,那么他们可以使用(:use ...)并明确处理核心。但是你选择操作符前缀似乎是一个糟糕的妥协。
(我还没有看到任何使用单字母前缀的库)。
另外一个可能性是提供上述内容和一个包含长名称而不是操作符的单独包(这些名称只是被定义为与原始包中的值匹配)。然后,如果人们想要(:use ...)但又想避免冲突,他们可以使用它(但真的(vector-add ...)有什么优势比(vector/+ ...)好吗?)
最后,我会检查+如何实现,因为如果它已经涉及某种类型分派,那么georgek的评论就很有道理了。
(在上面的“操作符”中,我只是指单个字符、非字母数字符号)。

谢谢-一些有益的想法!我最终选择了较长的名称,并提供了一些短别名,以便用户使用。 - mikera

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接