2020/05/21 - [컴퓨터 전공 공부/프로그래밍언어론] - [프로그래밍 언어/Racket] Racket introduction - 컴도리돌이-(1)
2020/06/04 - [컴퓨터 전공 공부/프로그래밍언어론] - [프로그래밍언어/Racket] Macros - 컴도리돌이-(3)
macro
매크로(macro)란 새로운 구문(syntax)을 source 언어의 다른 구문으로 변환하는 방법이다.
;;형태는 다르지만 같은 의미인 두 개의 구문
e1 andalso e2
if e1 then e2 else false
(my-if x then y else z) ; (if x y z)
(my-if x else y then z) ; syntax error
Tokenization
토큰(token)이라 불리는 단위로 나누는 작업을 토큰화(tokenization)라고 부른다.
사실 racket에서 token의 개념을 이해 못했다. ML에서는 cond와 비슷한 역할을 했지만, racket에서는 구조체 지정한때 #: transparent에서 밖에 확인을 못한거 같다.
example : "macro expand head to car"
- bad example (+ headt foo) to (+ cart foo)
- bad example head-door to car-door
Parenthesization
# define ADD(x,y) x+y // c,c++ 예
c언어로 예를 들자면 ADD라는 두 변수를 더하는 연산이 있으면 , ADD(1,2/3) * 4라는 연산은 1 + 2 /3 * 4 가 아니라
(1+2/3) * 4 연산을 의미 한다.
#define ADD(X,Y) ((X) + (Y))
C 매크로(macro)를 작성할 때에는 ADD라는 정의를 위에 코드처럼 정의한다.
racekt에서 매크로(macro)는 역시 생각나는게 있을것이다. 바로 local binding에서 언급하였던 let, let* letrec, define 이다.
(let ([head 0][car 1]) head) ; 0
(let* ([head 0][car 1]) head) ; 0
(let ([car 0][car 1]) car) ; error
(let* ([car 0][car 1]) car) ; 1
세 번째 let에서는 왜 에러가 나고, 네 번째 let*에서는 왜 에러가 안날까?
세 번째에서는 car이라는 두 개의 인자를 반복적으로 사용해서 에러가 났다. 하지만 let*에서 car은 전에 car에서 local binding했던 값을 그대로 다시 사용하기 때문에 중복으로 사용된게 아니다.
Quote
(define x (quote (list a b c))
; or
(define x '(list a b c))
Quasiquote
(define x (quasiquote
(list (unquote a)
(unquote b)
(unquote c))
; or
(define x `(list ,a ,b ,c))
Local variables in macros
(define-syntax dbl
(syntax-rules ()
[(dbl x) (let ([y 1])
(* 2 x y))]))
(define-syntax dbl2
(syntax-rules ()
[(dbl x) (* 2 x)]))