2019년 9월 11일 수요일

[on lisp] 12.3 new utilites

;; 12.3 New Utilities
; 이번에는 generalized variables에 관련된 새로운 유틸리티들을 볼 예정.
; 인수를 그대로 [setf]에 전달하려면 매크로 여야함.
; Fig 12.1는 setf을 이용한 예제를 보여줌.

(setf x nil y nil z nil)
;; 이럴거면 이제
(nilf x y z)
;; 이렇게 쓸 수 있다.
;; 이 4개의 매크로는 꽤나 중요한 점을 보여준다. 바로 값을 할당하는 연산자를 보여준 것이다.
;; Even if we only intent to use an operator on ordinary variables, it's worth wrting it to expand into a [A] instead of a [B]
; 일반 변수에만 연산자를 사용하려는 경우에도, setq보단 setf로 확장하도록 작성하는 것이 좋다.
; setq는 set qoute의 약자며 setf는 set function의 약자다
; q는 저장될 첫번째 매개변수로 이름만 올 수 있지만, setf는 함수도 올 수 잇다.

; Fig 12.2 에는 리스트의 끝을 파괴적으로 수정하기위한 3개의 매크로가 포함되어 있다.
; nconc란 사이드이펙트를 일으키는 conc (합치기) 첫번째 매개변수에 값이 더해지는 방식 (새로운 객체를 리턴하는게 아니라)

;; Fig 12.2 List operations on generalized variables.
(define-modify-macro concf (obj) nconc)

(define-modify-macro conc1f (obj)
(lambda (place obj)
(nconc place (list obj))))

(define-modify-macro concnew (obj &rest args)
(lambda (place obj &rest args)
(unless (apply #'member obj place args)
(nconc place (list obj)))))

; 우리는 이전에 (nconc x y)가 사이드이팩트를 일으킨다고 이야기 했다. 그리고 아래처럼 작성해야 한다.
(setq x (nconc x y))
;; 이런 형태를 매크로로 만드는 것이다. 그것이 concf다.
; conc1f는 새로운 요소를 리스트 뒤에 붙인다.
; concnew는 conc1f와 같지만 오로지 멤버에 없을 경우만이다.

;; 섹션 2.2에서 함수는 lambda-expression일 뿐만 아니라 symbol이 될 수 있다 했다.
; Thus it is find to give a whole lambda-expression as the third argument to [define-modify-macro], as in the definition of [conc1f]
; 따라서 define-modify-macro의 세번째 매개변수로 람다표현식 전체를 넣어도 된다.
; conc1 (45페이지)의 내용을 쓰자.
; page45 (Fig4.1 Small functions which operate on lists)
(defun conc1 (lst obj)
(nconc lst (list obj)))

(define-modify-macro conc1f (obj) conc1)
; conc1f라는 이름에
; define-modify-macro는 3개의 매개변수를 받는다.(다시씀)
; 1, name of the macro
;2. its additional parameters (after the generalized variable),
;3. the name of the function which yields the new value for the generalized variable

댓글 없음:

댓글 쓰기