2017-11-02 1 views
0

여기 내가 처음 일을 macroexpanding에 clojure는 컴파일 할 때 코드를 어떻게 평가합니까?

(defmacro hello [x] (eval '(+ 1 2)))

&

(defmacro hello [x] '(+ 1 2))

을 쓴 두 매크로입니다, 나는 (+ 1 2)를 얻고, 두 번째 macroexpanding 동안, 나는 값 3을 얻는다. 이것은 컴파일 타임에 추가 된 것을 의미합니까? 어떻게 가능할까요? '(+ 1 2) 대신 db를 쿼리하는 함수를 작성했으면 어떨까요? 그것은 컴파일 타임에 DB를 쿼리합니까?

답변

7

매크로는 임의의 코드를 컴파일러에 주입합니다. 일반적으로, 목적은 (1 + 2)과 같은 사용자 정의 코드를 "사전 처리"하여 Clojure가 (+ 1 2)과 같이 이해하는 것으로 만듭니다. 그러나 실제로 원하는 경우 (DB 액세스 포함)을 컴파일 단계에 포함 할 수 있습니다. 결국 컴파일러는 범용 컴퓨터에서 실행되는 소프트웨어 일뿐입니다. 오픈 소스이므로 컴파일러 코드를 직접 수정하여 모든 작업을 수행 할 수 있습니다.

매크로를 사용하는 것은 코어 Clojure 언어를 확장하기 위해 최적화 된 기본 컴파일러 코드를 수정/확장하는 편리한 방법 일뿐입니다. 그러나 매크로는 유스 케이스에만 국한되지 않습니다 (실제로 미쳐지기를 원하면).


Turing Complete 컴파일러 전처리 기인 C++ 표현식 템플릿 메커니즘을 사용하는 비슷한 기능이 있습니다. 유명한 예는 컴파일러를 사용하여 처음 몇 개의 소수를 "오류"메시지로 계산하는 것이 었습니다. http://aszt.inf.elte.hu/~gsd/halado_cpp/ch06s04.html#Static-metaprogramming

2

매크로 본문은 컴파일 타임에 실행되며 반환 값은 코드에서의 사용을 대체하기 위해 사용되며이 새 코드는 컴파일됩니다.

따라서 매크로 코드 :

(defmacro hello [x] (eval '(+ 1 2)))

실제로 그것의 사용을 대체 매크로의 결과로 반환됩니다 컴파일하는 동안 형태 '(+ 1 2) 및 그 표현 ( 3)의 결과 값 eval를 실행합니다

(예 : (hello 0)).

+0

지금 나는 힘을 본다 : D –

관련 문제