25
18. Destructurning Destructuring is a generalization of assignment.

On lisp ch18

Embed Size (px)

Citation preview

Page 1: On lisp ch18

18. Destructurning

Destructuring is a generalization of assignment.

Page 2: On lisp ch18

Destructuring : 일반화시킨 대입작업 .

• 18.1 Destructuring on Lists

• destructuring 소개• list 를 destructruring 하는 법 .

• 18.2 Other Structures

• dbind(destructuing-bind) 의 구현에 대해 설명• 문자열 , 벡터 , 배열 , 구조체를 destructuring 하는 법 .

• 18.3 Reference

• 인스턴스를 destructuring 하는 법 .

• 18.4 Matching

• 패턴매칭에 대해서• if-match구현 (1, 2) 및 활용에 대해 설명 .

Page 3: On lisp ch18

18.1 Destructuring on Lists

• 대입 (assign)• seq, setf

• 접근 (access) & 대입 (assign) • destructuring-bind

Page 4: On lisp ch18

Destructuring-bind

• CLTL2에서 , Common Lisp 는destructurning-bind 란 새로운 매크로를추가했다 .

Page 5: On lisp ch18

Ex) destrucing-bind

• 코드가 짧아질 뿐만아니라 , 보다 명확해졌다 .

CLTL1에서는(let ((x (first lst)) (y (second lst)) (z (third lst))) (list x y z))

CLTL2 에 들어서는(destructuring-bind (x y z) lst (list x y z))

Page 6: On lisp ch18

Destructuring

• Destructuring 작업은 CLTL1 Common Lisp 에서도 존재했었다 .

• 지금은 따로 분리가 됬지만 , 사실destructuring-bind 은 매크로 매개변수

리스트를 분리시키는데 사용했던 코드이다 .

Page 7: On lisp ch18

18.2 Other Structures

• 리스트를 destructuring 하는데에는제한을걸 필요가없다 .

• 그렇지만 , 복잡한객체에는제한을두어야한다 .

• > (dbind (a (b . c) &rest d) '(1 "fribble" 2 3 4)• (list a b c d))• (1 #\f "ribble" (2 3 4))

Page 8: On lisp ch18

문자열과 백터• read-macro #\ - 문자를표현하기위해사용됨

• CL-USER> (coerce "123" 'list)• (#\1 #\2 #\3)

• read-macro #( - 벡터를표현하기위해사용됨• CL-USER> (vector 1 2 3)• #(1 2 3)• CL-USER> (make-array 3 :initial-contents '(1 2 3))• #(1 2 3)• CL-USER> (make-array '(2 3) :initial-contents '((1 2 3) (4 5

6)))• #2A((1 2 3) (4 5 6))

• *print-array*

Page 9: On lisp ch18

Dbind

• 지금까지 봐왔던 매크로들과 비교하자면 , dbind 는 규모가 큰 편이지만 ,

• Lisp 프로그래밍에 관한 general lesson 을담고있기에 , 단순히 어떻게 동작하는지 이해하는데 그치는게 아니라 , 이 매크로의

구현에 대해 공부할 가치가 있다 .

Page 10: On lisp ch18

Ex) Dbind• (defmacro dbind (pat seq &body body)

(let ((gseq (gensym))) `(let ((,gseq ,seq)) ,(dbind-ex (destruc pat gseq #'atom) body))))

• dbind 는 destructuring-bind 처럼 런타임시 주어진 시퀀스가 예상했던원소를 얻지못한다면 , 에러를 발생한다

Page 11: On lisp ch18

Ex) with-

• with-matrix• 배열의순서 에기반

• with-array• 배열의좌표 에기반

• with-struct• 구조체의 prefix 와필드 name 에기반

Page 12: On lisp ch18

18.3 Reference

• let 대신 symbol-macrolet 으로 확장되게만듬으로써 , call-by-name 버전의destructuring 매크로를 만들 수 있다 .

Page 13: On lisp ch18

ex) with-places• (defmacro with-places (pat seq &body body)

(let ((gseq (gensym))) `(let ((,gseq ,seq)) ,(wplac-ex (destruc pat gseq #'atom) body))))

• Wplac-ex 내부는 앞선 dbind-ex 와 유사하며 , let 이symbol-macrolet 으로 바뀌었다 .

Page 14: On lisp ch18

18.4 Matching

• destructuring 이 일반화된 대입작업이라면 , 패턴매칭 은 일반화된 destructuring이다 .

• ``패턴매칭 '' 이란 용어는 여러 의미를 지니고있지만 , 여기선 , 변수를 포함하고있는 두 자료구조를 비교하여 , 두개가 동일하면

변수에 값을 대입 하는 것을 의미하기로 한다 .

Page 15: On lisp ch18

단일화 (Unification)• 패턴매칭과 단일화는 다르다 .• 패턴매칭은 단방향 , 단일화는 양방향• X = Y

X = 5• 패턴매칭에선 첫번째 라인부터 에러 (Y 가 bind 되지 않았기에 ) –

Erlang• 단일화에선 Y 는 5 의 값을 갖게됨 . – Prolog

• http://stackoverflow.com/questions/4442314/differences-between-pattern-matching-and-unification

• Unification 은 pattern matching …을 제네럴하게 .

Page 16: On lisp ch18

Match

• 인자로 받은것을 원소끼리비교하여 변수에 값을 대입 할 수 있도록 만들어 줌 (bindings).

• (match '(p ?x b ?y a) '(p ?y b c a))• ((?Y . C) (?X . ?Y)) ;; 매치시 cons 로묶어줌• T ;; 매치했는지알려주는 flag

Page 17: On lisp ch18

Ex)match

(defun match (x y &optional binds) (acond2 ((or (eql x y) (eql x '_) (eql y '_)) (values binds t)) ((binding x binds) (match it y binds)) ((binding y binds) (match x it binds)) ((varsym? x) (values (cons (cons x y) binds) t)) ((varsym? y) (values (cons (cons y x) binds) t)) ((and (consp x) (consp y) (match (car x) (car y) binds)) (match (cdr x) (cdr y) it)) (t (values nil nil))))

Page 18: On lisp ch18

if-match ( 1 )

• (defun abab (seq)(if-match (?x ?y ?x ?y) seq

(values ?x ?y)nil))

• 앞선 match 와 binding 을 이용하여 if-match 를 구현 .

Page 19: On lisp ch18

Ex) if-match ( 1 )

(defmacro if-match (pat seq then &optional else) `(aif2 (match ',pat ,seq)

(let ,(mapcar #'(lambda (v) `(,v (binding ',v it)))

(vars-in then #'atom)) ,then) ,else))

Page 20: On lisp ch18

If-match ( 2 ).1

• 앞선 if-match(1) 은짧지만 , 런타임시 너무많은 일을함 (비효율적임 )

• 이번에소개할 if-match(2) 는길지만 , 컴파일시 많은일을함 .

• If-match “의첫번째인자로들어오는것을” “ ” 일반변수 가아닌 패턴변수 로제한한다면 , 컴파일시 Match 에관여하는변수를알수있을것이다 .

Page 21: On lisp ch18

If-match ( 2 ).2

• “ ” 패턴변수 는 Quote 되는게 아니라 , 평가된다 .• “일반변수” “와 quote 된표현식” “ ” 을 패턴변수 로

이용할수있다 .

Page 22: On lisp ch18

Ex) if-match ( 2 )• (defmacro if-match2 (pat seq then &optional else)

`(let ,(mapcar #'(lambda (v) `(,v ',(gensym))) (vars-in pat #'simple?))

(pat-match ,pat ,seq ,then ,else)))

• (defmacro pat-match (pat seq then else) (if (simple? pat) (match1 ….. ---- A (with-gensym …… ---- B

• A – 뒤에계속• B - gensym “ ” 에의해 패턴변수 는 bind 되지않았기에 , binding

하는코드를생성함

Page 23: On lisp ch18

Ex) match1

• (defun match1 (refs then else) (dbind ((pat expr) . rest) refs (cond ((gensym? pat) …. -- A ((var? pat) ….. -- B

• A : length-test• B : binding작업

Page 24: On lisp ch18

394p - 244

• ?x 를 재활용하고자 한다면 ?• (if-match (?x . ?rest1) lst1

(if-match (?x . ?rest2) lst2?x))

• 추후에 나올 19 장 with-answer과 , 24 장의 with-inference 로 해결

Page 25: On lisp ch18

마치며• 간단한 ? Destructuring 에서 시작하여 ,

멋드러진 match 까지 살펴봄 .

• 나머지 장에서는 이러한 철학에 기반을 둔 프로그램에 대해 설명함 .