함수 f의 보수는 ∼f로 표기된다.
5.1절에서 closure가 ∼을 Lisp 함수로 정의할 수 있게 함을 보였다.
함수에 대한 또 다른 공통 연산은 연산자 ◦로 표시되는 '합성'이다.
f와 g가 함수라면, f ◦g는 함수이고 f ◦g (x) = f (g (x))이다.
클로저는 또한 ◦을 Lisp 함수로 정의하는 것을 가능하게합니다
아래 Figure5.3은 여러 함수를 취해 그 혼합물을 리턴하는 compose함수를 정의한다.
;; Figure 5.3: An operator for functional composition. ;; 1. &rest는 복수의 함수를 매개변수를 받겠다. ;; 2. 함수가 존재한다면 ;; 2.1 리스트의 마지막 함수 가져오기 (compose는 오른쪽부터 합쳐진다) ;; 2.2 fn1 함수가 어떤 매개변수를 받을지 모르지 args로 다 받음 ;; 2.3 마지막 함수를 제외한 함수 리스트를 구함(마지막 리스트는 초기값에 들어감) ;; 2.4 reduces로 하나하나 함수를 누산한다. ;; 2.5 :from-end t 뒤에서 부터 실행하라는 뜻 ;; 2.6 :initial-value 첫번째 함수를 초기값으로 세팅 ;; 3. 함수가 없으면 identity 리턴 (defun compose (&rest fns) ;; 1 (if fns ;; 2 (let ((fn1 (car (last fns))) ;; 2.1 (fns (butlast fns))) ;; 2.2 #'(lambda (&rest args) ;; 2.3 (reduce #'funcall fns ;; 2.4 :from-end t ;; 2.5 :initial-value (apply fn1 args)))) ;; 2.6 #'identity)) ;; 3 ;; 사용법 (compose #'list #'1+) ;; 아래 값과 같다. #'(lambda (x) (list 1+ x))compose에 대한 인수로 주어진 모든 함수는 마지막 인수를 제외하고, 모두 하나의 인수를 받는 녀석들이어야 한다.
마지막 함수는 아무런 제약이 없다. 무엇이든지 인수가 주어지면 compose에 의해 함수가 초깃값으로 반환될 것이다.
> (funcall (compose #’1+ #’find-if) #’oddp ’(2 3 4)) 4위에 내용은 함수들을 closure로 감싼 함수를 리턴한 것과 같다.
;; Figure 5.4: More function builders. (defun fif (if then &optional else) #'(lambda (x) (if (funcall if x) (funcall then x) (if else (funcall else x))))) (defun fint (fn &rest fns) (if (null fns) fn (let ((chain (apply #'fint fns))) #'(lambda (x) (and (funcall fn x) (funcall chain x)))))) (defun fun (fn &rest fns) (if (null fns) fn (let ((chain (apply #'fun fns))) #'(lambda (x) (or (funcall fn x) (funcall chain x))))))not은 리스프 함수이기 때문에, complement는 compose의 특별한 경우이다.
이녀석은 이렇게 정의될 수 있다.
(defun complement (pred) (compose #'not pred))함수들을 조합(composing)하는 것 이외의 다른 방법으로 기능을 결합(combine)할 수 있다.
(mapcar #'(lambda (x) (if (slave x) ; 노예면 (owner x) ; 오너를 (employer)) ; 아니면 고용주를 people) ; 사람 , 노예 아니면 직장인위와 같은 함수를 자동으로 생성하는 연산자를 정의할 수 있다.
Figure 5.4의 fif를 사용하면 다음과 같은 효과를 얻을 수 있다.
(mapcar (fif #'slave #'owner #'employer) people)아주 간단해졌다.
fif코드에 대해 알아보자.
1. if, then, else를 담은(closure) 람다함수 리턴
1.1 람다는 true/false 값을 받는다.
2. then 걸린 함수 실행
3. else
(defun fif (if then &optional else) #'(lambda (x) ; (if (funcall if x) ; 1 (funcall then x) ; 2 (if else (funcall else x))))) ; 3
Figure 5.4는 일반적으로 발생하는 유형의 함수에 대한 몇 가지 다른 생성자를 포함한다.
두 번째, fint는 다음과 같은 경우입니다.
트루이면 그 상태에서 멈추는 거니까 거기까지만 일을 했다는 것! 특이한 건 그때그때 함수를 실행할 것이겠지?
and이니까 그럴 것이다.(and는 매크로로 보임)
;; 아래 소스는 signed,sealed,delivered가 모두 참인경우
(find-if #'(lambda (x) (and (signed x) (sealed x) (delivered x))) docs)find-if의 인수로 주어진 predicate(술어)는 그 안에서 호출되는 세 개의 predicates의 교차점(intersection)이다.
그러니까 모두 참인경우를 말한다. 교집합
"function intersection"을 뜻하는 fint를 사용해보자.
(find-if (fint #'signed #'sealed #'delivered) docs)이렇게 유사한 연산자를 정의하여 predicate집합의 합집합을 반환 할 수 있따.
fun 함수는 fint와 비슷하지만 and 대신에 or를 사용한다.
fun = find-union (이렇게 보면 될듯)
댓글 없음:
댓글 쓰기