2016-09-05 3 views

답변

1

내가 방금 네임 스페이스에서 그것을을 그림자의 clojure.core 기능 +을 제거하고 생각하지 않습니다.

user=> (def + -) 
#'user/+ 
user=> (+ 2 2) 
0 
user=> (def + clojure.core/+) 
#'user/+ 
user=> (+ 2 2) 
4 

을하지만 .... 왜?! :

당신은 네임 스페이스 포함을 참조하여 clojure.core에서 함수로 +를 redeffing하여 다시 얻을 수 있습니다

2

@ Russell이 말했듯이 clojure.core/+의 섀도우 잉은 user/+입니다.

내가 Clojure의 실험에 대해 어떻게 할 것인지, (엉망으로하고 싶지 않아 다시 +과 핵심 +를 미행하지만, 바인딩 범위 내에서 변경을 유지) 단지 일부 지역의 바인딩을 설정하는 것입니다 :

user> (let [+ -] 
     (+ 1 2 3)) 
-4 

user> (+ 1 2 3) 
6 

그러나 당신이 원하는 것을 할 수있는 특별한 방법이 일반적으로 (즉, VAR의 값을 변경 VAR 변경 범위에서 일부 코드를 실행 한 다음 자동으로 값의 복원하는) :

첫 번째 binding (https://clojuredocs.org/clojure.core/binding) 문제를 사용하는 것입니다. 입니다 만 특별한 dynamic 바르 작동, 그래서 +

두 번째 동적 아니기 때문에 그것은 귀하의 경우 실제로 적용 할 수 없습니다, 당신이 필요로 가까이되는 with-redefs (https://clojuredocs.org/clojure.core/with-redefs)를 사용하는 것입니다,하지만 하나가 이 문제 :

user> (with-redefs [+ -] 
     (+ 1)) 
-1 ;; as expected 

user> (with-redefs [+ -] 
     (+ 1 2 3)) 
6 ;; unexpected! 

두 번째 예는 실패, 컴파일러의 인라인 때문에 + 기능, 하나 개 이상의 인수가 자신에게 전달하고 일부 순수 educat를 들어,

또한) add 함수 호출로 대체하는 경우 추가 기능의 컴파일러의 인라인에 흥미 잡았다이다

user> (defmacro redefine [old new & body] 
     `(let [v# ~old] 
      (def ~old ~new) 
      (let [res# (do [email protected])] 
      (def ~old v#) 
      res#))) 
#'user/redefine 

user> (redefine 
     + - 
     (+ 1 2 3)) 
-4 

user> (+ 1 2 3) 
6 

user> #'+ 
#'user/+ 

user> (redefine 
     + * 
     (+ 1 2 4)) 
8 

user> (redefine 
     + * 
     (+ 1 2 4)) 
8 

user> (+ 1 2 4) 
7 
+0

:하는 ional 목적 당신은, 즉 일반적으로 당신이 필요로하는 모든 것을, 이전 값을 저장하고, 블록 평가 후 복원을 다시 정의 할 매크로를 만들 수 있습니다! – Russell

+0

이것은 훌륭한 대답이지만 Clojure를 처음 접한다면 가능한 한 오랫동안 매크로를 피하는 것이 좋습니다. @Atonal ... 필요한 경우는 거의 없지만 사용하는 경우는 거의 없습니다. 코드 이해 가능성 측면에서 미미한 비용이며 초보자/중간체에서 종종 과용됩니다. – Russell

+0

@Russell 나는 매크로가 약간의 복잡성을 추가하고 때로는 초보자에게 특히 이해하기가 어렵다고 동의하지만, 반면에 그것은 리스프를 마일로 돋보이게하는 환상적인 도구이다. "피하는"대신 "반응 형으로 사용") – leetwinski

관련 문제