람다표현식을 사용할 때, defun을 사용할 때는 직면하지 않았던 문제에 직면하게 된다.
람다표현식은 이름이 없기 때문에 자기 자신을 부를 방법이 없다.
그래서 커먼리습에선 재귀를 람다만으로 구현할 수 없다.
예를들면
(mapcar #'(lambda (x) (+ 2 x)) '(2 5 7 3)) ;; (4 7 9 5)만약 여기서 재귀함수를 넣고 싶다면?
(mapcar #'copy-tree '((a b) (c d e)))이렇게 그냥 넣으면 된다. 하지만 람다는?
label이라는 녀석을 사용하면 된다.
(labels ((inc (x) (1+ x))) (inc 3)) ;; 4labels는 let의 함수버전이라고 생각하면 된다.
(defun count-instances (obj lsts) (labels ((instances-in (lst) (if (consp lst) ;; list면 (+ (if (eq (car lst) obj) 1 0) ;; obj와 같냐 틀리냐고 1,0으로 나뉘고 (instances-in (cdr lst))) ;; 재귀적으로 나머지 리스트를 다시 호출해서 obj('a)가 몇개 있는지 확인한다. 0))) ;; 리스트가 아니면 0 (mapcar #'instances-in lsts))) (print (count-instances 'a '((a b c) (d a r p a) (d a r) (a a)))) ;; 각 리스트에 'a가 몇개 있는지 ;; 1 2 1 2이렇게 쓸 수 있다.
라벨링을 일단 하고 사용할 함수에 그 녀석을 넣으면 된다.
댓글 없음:
댓글 쓰기