2010-02-28 5 views

답변

8

Clojure 1.1.0 이상에서 두 개의 인수가있는 +은 성능을 위해 인라인됩니다. 바인딩이 너무 늦게 발생합니다. 더 많은 논쟁들과 다르게 작동합니다.

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

한 가지 해결 방법은 자신 만의 공간을 만들어 자신의 기능을 clojure.core/+ 그림자입니다.

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

Clojure 1.2.0의 현재 스냅 샷에서 인라인은 더욱 적극적으로 수행됩니다.

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

+, 예 이외의 함수 이름을 사용할 수있다 현명한 add, 혼동을 피하기 위해.

+0

그들은 Clojure 1.2.0의 최종 빌드에서이 공격적인 인라이닝을 가져 왔음에 틀림 없습니다. 마지막 표현에서 나에게 -4가 주어지기 때문입니다. –

6

빠른 해결 방법 : 바인딩 대신 을하게 사용이 잘 당신을 위해 작동합니다 :

테이크 :


약간의 (불완전) 이유 파고

user=> (let [+ list] (+ 2 3)) 
(2 3) 
+ 함수의 출처에 대한 살펴보기 :

(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))) 

서로 다른 수의 인수에 대해 여러 개의 인라인 함수 정의가 있음에 유의하십시오. 당신이 0 또는 1 인수에 대응 정의를 리 바인드하려고하면, 그것은 잘 작동 : (당신이 발견으로)

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

지금이 확실히이 인수의 경우 작동하지 않습니다. 저는 점들을 연결하는 것이 아니라, 점들을 연결하고 있습니다. (특수 폼)는 매크로가되는 바인딩과 결합되어 의심 스럽습니다. 반면에 let은 특별한 형식입니다 ...

특히 아티 2를 불러오는 메타 데이터도 의심스러워 보입니다.

관련 문제