2013-07-10 5 views
4

나는 이처럼 정의 된 함수 스펙을 가지고 있으며 이것을 전달할 수 있도록 함수 오브젝트로 평가하려고합니다.목록 양식을 clojure의 함수로 변환하는 방법

(def spec '(foo [n] (* 2 n))) 

나는이

(defmacro evspec [name arg & body] `(defn ~name [~arg] [email protected])) 

다음 호출이 날 줄 것이다 함수 foo와 같은 매크로를 만들 수 있습니다. 3 호출 할 때, (foo는 3), 내가 위에서 정의 된 내 사양에서 함수 본문을받을 경우 함수 foo 실 거예요 (* 2 n)은 몸의 양식을 평가 반환, 그러나 6

(evspec foo n (* 2 n)) 

를 반환합니다 대신, 본문 양식을 반환합니다.

(let [foo (first spec) arg (first (second spec)) body (last spec)] 
    (evspec foo arg body)) 

user=> (foo 3) 
(* 2 n) 

나는 작업 foo는 기능이

user=> foo 
#<user$foo [email protected]> 

아무도의 차이입니다 이유를 설명 할 수있는 동안 지금 만든 푸 기능은 $ 평가 후면 $ foo는

user=> foo 
#<user$eval766$foo__767 [email protected]> 

예고하고 어떻게 할 수 작동하게 만들다 ? eval에 회신하지 않고 방법을 갖고 싶습니다. 자바 스크립트 배경에서 오는 어쨌든 나는 항상 eval이 악하다고 생각한다.

+0

함수 객체를 전달하려면 defn foo [...]를 사용하고 심볼 foo를 전달하면됩니다. –

답변

4

eval 없이는 일반적으로 수행 할 수 없습니다. 매크로는 단순히 컴파일 타임에 인수 표현식을 그대로 전달하는 함수입니다 (일반적으로 런타임시 자신의 값이 무엇인지 알기는 근본적으로 불가능합니다). 특히, 반환 값은, (* 2 n) 인 질문 텍스트의 let 형태, 내부 evspec에 대한 호출에 evspec 매크로 확장은 문자 그대로 기호 foo과 그 위치 인수 및 (body)로 기호 n (하나의 기호를 포함하는 서열을 본다 body)를 "나머지"인수로 사용합니다. 반환 값은 이러한 입력 값과 일치합니다.

그러나이 용도로 eval을 사용하면 문제가 없습니다. 상당한 런타임 비용이 있다는 것을 염두에 두는 것이 중요하므로 다소 익숙하지 않게 사용하고 싶지만 일단 eval을 사용하여 함수를 생성하면 다른 모든 Clojure 함수와 마찬가지로 완벽하게 좋은 Clojure 함수입니다.

또한 JavaScript에서 eval은 텍스트를 처리하지만 Clojure의 eval은 실제로 Clojure 데이터 구조에서 작동합니다. 사실 동일한 데이터 구조 매크로가 작동하기 때문에 틀림없이 오류가 발생하기 쉽습니다.

+0

+1 데이터 구조에 대한 clojure eval에 대해 js eval on text! – haijin

관련 문제