2011-06-27 51 views
16

覆盖诸如“+”之类的方法的正确方法是什么?现在我有clojure - 本地覆盖运算符(例如“+”,“*”等)的正确方法

(defn- + [x y] (replacement x y)) 

但这会在命令行中产生警告。

WARNING: + already refers to: #'clojure.core/+ in namespace: <MY-NAMESPACE>, being replaced by #'<MY-NAMESPACE>/+ 
+0

对于Clojure的新手来说,这个问题不是关于面向对象意义上的'重写'(Clojure不是面向对象的)。真正问题在于如何防止警告当全局变量反弹时触发。第一个绑定发生是因为使用'ns'宏引入了clojure.core的映射。 (请参阅http://clojure.org/namespaces)当本地文件重新绑定var时,会发生第二次绑定。 –

+0

另外,更多术语:Clojure没有方法。它有功能。 –

回答

29

你需要排除由核心导入功能:

(ns your-ns 
    (:refer-clojure :exclude [+ ...])) 

(defn + ...) 
3

您确定要这样吗?如果是的话,你可以使用defprotocol来指定​​你想要覆盖的操作符,并扩展你希望实现这些覆盖的类。对于(人为)例如看到我answer to this question.

+0

是的,我确定,我正在尝试编写DSL。好的解决方案,谢谢! – gatoatigrado

4

虽然我不建议重写核心功能,如+,你可以使用绑定或者让这一点,它取决于你想要什么样的行为:

(let [+ -] (redu­ce + [1 2 3])) ; -4 
(defn my-pl­us [x] (redu­ce + x)) 
(let [+ -] (my-p­lus [1 2 3])) ;6 
(binding [+ -] (my-p­lus [1 2 3])); -4 

像在下面的评论中已经说过了,自从clojure 1.3以来,绑定不再起作用,因为var应该是动态的,而+, - 等不是。

出于测试目的/嘲笑,你可能会得到类似的行为。在这种情况下,看看有-redefs(因为Clojure的1.3): http://clojuredocs.org/clojure_core/clojure.core/with-redefs

另见: Let vs. Binding in Clojure

+2

将无法​​在clojure 1.3下工作 - '+'未被标记为动态,并且不能被重新绑定 – aav

+0

@aav - 对于绑定可能是正确的,但let版本仍然可以工作(因为let是词法绑定) – mikera

+0

同意 - 让我们工作 – aav