Подтвердить что ты не робот

Clojure - правильный способ локального переопределения операторов, таких как "+", "*" и т.д.

Каков правильный способ переопределить метод типа "+"? Прямо сейчас у меня

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

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

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

Ответ 1

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

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

 (defn + ...)

Ответ 2

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

(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

Также смотрите: Пусть vs. Binding в Clojure

Ответ 3

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