2011-06-27 8 views
16

¿Cuál es la forma correcta de anular un método como "+"? En este momento tengoclojure - forma correcta de anular localmente operadores como "+", "*", etc.

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

pero esto ocasiona advertencias en la línea de comandos.

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

Para ser claros, para los más nuevos de Clojure, esta pregunta no se trata de 'sobrescribir' en un sentido orientado a objetos (Clojure no está orientado a objetos). Realmente lo que la pregunta es cómo prevenir la advertencia que se activa cuando una var global se rebota. La primera vinculación ocurre porque el uso de la macro 'ns' trae asignaciones de clojure.core. (ver http://clojure.org/namespaces) El segundo enlace ocurre cuando un archivo local vuelve a enlazar la var. –

+0

Además, más terminología: Clojure no tiene métodos. Tiene funciones. –

Respuesta

29

necesita excluir las funciones que se importan por el núcleo:

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

(defn + ...) 
3

¿Estás seguro de que quieres hacer esto? En caso afirmativo, podría usar defprotocol para especificar qué operadores desea sobrescribir y extender las clases para las cuales desea que se implementen estas modificaciones. Para un ejemplo (artificial) ver mi answer to this question.

+0

Sí, estoy seguro, estoy tratando de escribir un DSL. Buena solución, gracias! – gatoatigrado

4

Aunque no recomiendo anulando funciones básicas como +, se puede usar o dejar de unión para esto, depende de lo que el comportamiento que desea:

(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 

igual se ha dicho en los comentarios a continuación, el enlace ya no funciona así desde clojure 1.3, ya que la var debe ser dinámica y +, -, etc. no lo son.

Para fines de prueba/burla, sin embargo, podría obtener un comportamiento similar. En ese caso, mira con-REDEFS (desde clojure 1.3): http://clojuredocs.org/clojure_core/clojure.core/with-redefs

Véase también: Let vs. Binding in Clojure

+2

no funcionará bajo clojure 1.3 - '+' no está marcado como dinámico, y no puede volverse a enlazar – aav

+0

@aav - puede ser cierto para el enlace, pero las versiones de let deberían funcionar (ya que let es un enlace léxico) – mikera

+0

de acuerdo - déjame trabajar – aav

Cuestiones relacionadas