2013-02-07 2 views
12

다른 사람의 Clojure의 코드를 볼 때 때때로, 나는 기능은 예를 들어, defn를 통해 정의하고 VAR 인용 구문을 사용하여 호출을 참조하십시오의 수명을사용하여 Clojure의 함수 호출 VAR 인용 구문

user> (defn a [] 1) 
#'user/a 
user> (a) ; This is how you normally call a function 
1 
user> (#'a) ; This uses the var-quote syntax and produces the same result 
1 

나는 함수를 호출하는이 두 가지 방법의 차이를 이해할 수 없다. evaluation 설명서에서 호출 연산자가 왜 두 번째 형식이 선호 될지 제안 할 수있는 var 일 때 어떤 일이 발생하는지 알 수는 없습니다. 이들은 모두 binding 할당 및 구문 인용에 응답하는 것으로 보입니다.

위의 코드에서 (a)(#'a)의 차이점을 보여주는 코드 샘플을 제공해주십시오.

편집 : 내가 var에 따옴표가 let 어휘 결합에 의해 그림자있어 var에 도착하는 데 사용할 수 있다는 것을 알고 있지만, 내가 찾고 있어요 코드의 경우 될 것 같지 않습니다.

user> (defn a [] 1) 
#'user/a 
user> (let [a (fn [] "booh")] [(a) (#'a)]) 
["booh" 1] 

그러나 대부분의 실제 VAR 인용/함수 호출의 용도 직접 VAR 인용 식을 호출되지 않습니다 (a) 로컬 바인딩에 의해 그림자가 될 수있는 반면

답변

16

(#'a)는 항상 VARa을 말한다

(defn a [] 1) 
(defn my-call [f] (fn [] (+ 1 (f)))) 
(def one (my-call a)) 
(def two (my-call #'a)) 
(defn a [] 2) 

user> (one) 
2 
user> (two) 
3 

이 m이다 전달시 고차 구조가 VAR 대신 값의 현재 값을 참조하도록, 대신에 그 값을 캐시 대화 형 개발에 유용하며, 다른 패키지에서 다른 함수 묶음으로 묶인 일부 함수를 변경합니다.

6

두 번째 형식을 사용하면 클로저에 명시된 개인 정보 보호 제한을 우회 할 수 있습니다.

예를 들어 개인 기능이있는 라이브러리를 개발했지만 별도의 네임 스페이스에서 테스트하려는 경우 직접 참조 할 수 없습니다. 하지만 var quote 구문을 사용하면 얻을 수 있습니다. 이것은 매우 유용합니다.

개인 정보 보호는 기본적으로 자동 문서 형식이며, Java에서 보는 개인 정보 보호와는 다릅니다. 주변을 둘러 볼 수 있습니다.

user> (defn- a [] 1) 
#'user/a 
user> (ns user2) 
nil 
user2> (user/a) 
CompilerException java.lang.IllegalStateException: var: #'user/a is not public, compiling:(NO_SOURCE_PATH:1) 
user2> (#'user/a) 
1 
user2> 
+0

좋은 지적 - 이제는 내가 언급 한대로 과거에이 작업을 수행 한 것을 기억합니다. 그러나 내가보고있는 코드는 비공개 fn을 호출하는 것이므로 현재 바인딩 된 값의 캐싱을 피하는 것이 가장 가능성있는 설명이라고 생각합니다. – Alex

+0

코드가 개인 repo에 있기 때문에. 나는 일반적인 질문을 올렸고, 두 가지 좋은 대답을 얻었고 오직 하나만 받아 들일 수 있었다. 그래서 나는 일반적인 경우에 대해 더 잘 대답 할 수 있다고 느꼈던 것을 받아 들였다. – Alex