2010-02-28 12 views

risposta

8

In Clojure 1.1.0 almeno, + con due argomenti è inline per le prestazioni. La tua associazione avviene troppo tardi. Con più argomenti funziona diversamente.

Clojure 1.1.0-master-SNAPSHOT 
user=> (binding [+ -] (+ 1 2)) 
3 
user=> (binding [+ -] (+ 1 2 3)) 
-4 

Una soluzione è quella di rendere il proprio spazio dei nomi e ombra clojure.core/+ con la propria funzione.

user=> (ns foo (:refer-clojure :exclude [+])) 
nil 
foo=> (defn + [& args] (reduce clojure.core/+ args)) 
#'foo/+ 
foo=> (+ 1 2) 
3 
foo=> (binding [+ -] (+ 1 2)) 
-1 

Nota che inlining sembra accadere anche più aggressivo nello snapshot corrente di Clojure 1.2.0.

Clojure 1.2.0-master-SNAPSHOT 
user=> (binding [+ -] (+ 1 2)) 
3 
user=> (binding [+ -] (+ 1 2 3)) 
6 

Può essere saggio per utilizzare un nome funzione diversa +, ad esempio add, per evitare confusione.

+0

Devono aver preso questa inlining aggressivo dalla build finale di Clojure 1.2.0, perché l'ultima espressione mi dà -4. –

6

soluzione rapida: utilizzare cerchiamo invece di vincolante e questo sarà il lavoro per voi più che bene:

user=> (let [+ list] (+ 2 3)) 
(2 3) 

Un po '(incompleta) scavare nella ragione:

Prendere uno sguardo all'origine per la funzione +:

(defn + 
    "Returns the sum of nums. (+) returns 0." 
    {:inline (fn [x y] `(. clojure.lang.Numbers (add ~x ~y))) 
    :inline-arities #{2}} 
    ([] 0) 
    ([x] (cast Number x)) 
    ([x y] (. clojure.lang.Numbers (add x y))) 
    ([x y & more] 
    (reduce + (+ x y) more))) 

Si noti che esistono diverse definizioni di funzioni in linea per diversi numeri di argomenti. Se si tenta di associare nuovamente i 0 o 1 Definizioni arity, funziona bene:

user=> (binding [+ (fn [] "foo")] (+)) 
"foo" 
user=> (binding [+ (fn [a] (list a))] (+ 1)) 
(1) 

Ora, questo sicuramente non funziona (come hai scoperto) per il caso 2-argomento. Non sto abbastanza collegando i punti, ma il. (forma speciale) mi rende sospettoso combinato con l'associazione come macro mentre let è una forma speciale ...

Anche i metadati che richiamano in modo particolare l'arity 2 sembrano sospetti.

Problemi correlati