clojure — correct way to locally override operators such as “+”, “*”, etc

我怕爱的太早我们不能终老 提交于 2019-12-04 15:59:13

问题


What is the correct way to override a method like "+"? Right now I have

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

but this results in warnings on the command line.

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

回答1:


You need to exclude the functions that are imported by core:

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

 (defn + ...)



回答2:


Although I don't recommend overriding core functions like +, you could use binding or let for this, it depends on what behavior you want:

(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

Like it has been said in the comments below, binding doesn't work this way anymore since clojure 1.3, since the var should be dynamic and +,-, etc aren't.

For testing purposes/mocking you could however get similar behaviour. In that case look at with-redefs (since clojure 1.3): http://clojuredocs.org/clojure_core/clojure.core/with-redefs

Also see: Let vs. Binding in Clojure




回答3:


Are you sure you want to do this? If yes, you could use defprotocol to specify what operators you want to override and extend the classes for which you want these overrides implemented. For a (contrived) example see my answer to this question.




回答4:


You can also override built in arithmetic using generic interfaces from contrib, see the following for a simple example,

http://nakkaya.com/2010/08/02/using-clojure-contrib-generic-interfaces/



来源:https://stackoverflow.com/questions/6489555/clojure-correct-way-to-locally-override-operators-such-as-etc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!