clojure - правильный способ локального переопределения операторов, таких как "+", "*" и т. д. - PullRequest
18 голосов
/ 27 июня 2011

Как правильно переопределить метод, такой как «+»?Прямо сейчас у меня есть

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

, но это приводит к предупреждениям в командной строке.

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

Ответы [ 4 ]

33 голосов
/ 27 июня 2011

Вам необходимо исключить функции, импортируемые ядром:

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

 (defn + ...)
4 голосов
/ 27 июня 2011

Хотя я не рекомендую переопределять основные функции, такие как +, вы можете использовать привязку или позволить для этого, это зависит от того, какое поведение вы хотите:

(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, поскольку переменная должна быть динамической, а +, - и т. Д. - нет.

Для целей тестирования / насмешек вы можете получить похожее поведение. В этом случае посмотрите на with-redefs (начиная с версии 1.3): http://clojuredocs.org/clojure_core/clojure.core/with-redefs

Также см .: Пусть против связывания в Clojure

3 голосов
/ 27 июня 2011

Вы уверены, что хотите это сделать? Если да, вы можете использовать defprotocol, чтобы указать, какие операторы вы хотите переопределить, и расширить классы, для которых вы хотите реализовать эти переопределения. (Придуманный) пример см. Мой ответ на этот вопрос.

1 голос
/ 27 июня 2011

Вы также можете переопределить встроенную арифметику, используя общие интерфейсы из contrib, простой пример приведен ниже,

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

...