Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

clojure -- correct way to locally override operators such as "+", "*", etc

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>/+
like image 705
gatoatigrado Avatar asked Jun 27 '11 06:06

gatoatigrado


3 Answers

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

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

 (defn + ...)
like image 164
dnolen Avatar answered Sep 19 '22 04:09

dnolen


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

like image 36
Michiel Borkent Avatar answered Sep 20 '22 04:09

Michiel Borkent


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.

like image 21
Maurits Rijk Avatar answered Sep 23 '22 04:09

Maurits Rijk