20

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>/+
gatoatigrado
  • 16,580
  • 18
  • 81
  • 143
  • 1
    To be clear, for those newer to Clojure, this question isn't about 'overriding' in an object-oriented sense (Clojure isn't object-oriented.) Really what the question is asking is how to prevent the warning that is triggered when a global var is rebound. The first binding happens because using the `ns` macro brings in mappings from clojure.core. (see http://clojure.org/namespaces) The second binding happens when a local file rebinds the var. – David J. Dec 15 '13 at 02:43
  • Also, more terminology: Clojure doesn't have methods. It has functions. – David J. Dec 15 '13 at 02:45

4 Answers4

35

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

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

 (defn + ...)
dnolen
  • 18,496
  • 4
  • 62
  • 71
4

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

Community
  • 1
  • 1
Michiel Borkent
  • 34,228
  • 15
  • 86
  • 149
  • 2
    will not work under clojure 1.3 - '+' is not marked as dynamic, and cannot be re-bound – aav Jun 27 '11 at 16:11
  • @aav - may be true for binding, but the let versions should still work (since let is a lexical binding) – mikera Jun 27 '11 at 17:33
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.

Community
  • 1
  • 1
Maurits Rijk
  • 9,789
  • 2
  • 36
  • 53
1

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/