본문 바로가기

LISP

if / when / unless / cond / case / and / or / not + (predicates)


;;; (if (조건) 참-실행문 거짓-실행문)
;;; (if <test> <then form> <else form>)

CL-USER 1 > (setf day-or-date 'monday)
MONDAY

CL-USER 2 > (if (symbolp day-or-date) 'day 'date)
DAY

CL-USER 3 > (setf day-or-date 9)
9

CL-USER 4 > (if (symbolp day-or-date) 'day 'date)
DATE

CL-USER 5 > (if (numberp day-or-date) 'day 'date)
DAY

;;; (when (조건) 참-실행문들)
;;; (when <test> <then forms>)

;;; (if <test> <then form> nil)
;- i f 의 불필요한 <else form> 부분 평가가 필요없을 때,
;- 단순히 참인 경우만 확인하여 실행하고자 할 때

CL-USER 14 : 1 > (setf high 98 temperature 102)
102

CL-USER 15 : 1 > (when (> temperature high) (setf high temperature) 'new-record)
NEW-RECORD

CL-USER 16 : 1 > high
102


;;; (unless (조건) 거짓-실행문들)
;;; (unless <test> <else forms>)
;;; (if <test> nil <else form>)
;- i f 의 불필요한 <then form> 부분 평가가 필요없을 때,
;- 단순히 거짓인 경우만 확인하여 실행하고자 할 때



;;; (cond (조건 절1) (조건 절2) (조건 절3) ... (t 절))
;;; if, when, then 보다 훨씬 유연한 조건 실행을 위한 cond
;;; 즉, cond으로 위 모든 논리회로를 구성할 수 있다.
;;; 각 조건절 하나씩이 when 절과 같은 역할 수행 중
;;;; (cond (<test 1> <cosequnce 1-1> ...)
;;;;          (<test 2> <cosequnce 2-1> ...)
;;;;              ....
;;;;          (<test n> <cosequnce n-1> ...))
;- (when 1), (when 2), (when 3), ... (when n)의 경우를 한꺼번에 설정한 효과
;- <test> 중 nonNil인 것을 찾아서 실행하는 기능, 이를 triggered clause라 함.
;- 반환값은 triggered clause 중에서 마지막 consequnce form이 된다.
;- 모든 <test>가 Nil이면 전체 반환값은 Nil

CL-USER 17 : 1 > (setf thing 'sphere r 1)
1
CL-USER 18 : 1 > (cond ((eq thing 'circle) (* pi r r))
                                    ((eq thing 'sphere) (* 4 pi r r)))
12.566370614359173D0

CL-USER 19 : 1 > (cond ((eq thing 'circle) (* pi r r))
                       (t (* 4 pi r r)))                        ;;- 마지막 조건을 t로 하는 경우
12.566370614359173D0

CL-USER 20 : 1 > (cond ((eq thing 'circle) (* pi r r))
                       ((* 4 pi r r)))                        ;;- 마지막 조건을 안다는 경우
                                                                 ;;- 이는 test form이자 value form
12.566370614359173D0


CL-USER 22 : 1 > (setf p .6)
0.6

CL-USER 23 : 1 > (cond ((> p .76) 'very-likely)
                                     ((> p .5) 'likely)
                                     ((> p .25) 'unlikely)
                                     (t 'very-unlikely))
LIKELY

CL-USER 24 : 1 > (defun rightp (a b c)     ;; 변의 길이를 톻애 직각 삼각형 여부 판단
 (cond ((eq (max a b c) a) (eq (expt a 2) (+ (expt b 2) (expt c 2))))
           ((eq (max a b c) b) (eq (expt b 2) (+ (expt a 2) (expt c 2))))
           (t (eq (expt c 2) (+ (expt b 2) (expt a 2))))))
RIGHTP

CL-USER 25 : 1 > (rightp 3 4 6)
NIL

CL-USER 26 : 1 > (rightp 4 5 3)
T


CL-USER 37 : 7 > (setf breakfast '(egg bacon toast tea))
(EGG BACON TOAST TEA)

CL-USER 38 : 7 > (cond ((> (length breakfast) 10) 'glutton)
                       ((not (endp breakfast)) 'normal)   ;;; better
                       (t 'anorexic))
NORMAL

CL-USER 39 : 7 > (cond ((> (length breakfast) 10) 'glutton)
                       (breakfast 'normal)           ;;; breakfast가 notNil이기만 하면 실행
                       (t 'anorexic))
NORMAL


;; (not u) = (cond (u nil) (t t))
;; (or x y z) = (cond (x) (y) (t z))
;; (and a b c) = (cond ((not a) nil) ((not b) nil) (t c))

CL-USER 44 : 7 > (defun check-temperature (temp)
                               (cond ((> temp 100) 'rediculously-hot)
                                        ((> 0 temp) ' rediculously-cold)
                                        (t 'ok)))
CHECK-TEMPERATURE

CL-USER 45 : 7 > (check-temperature 122)
REDICULOUSLY-HOT

CL-USER 46 : 7 > (check-temperature 33)
OK

CL-USER 47 : 7 > (check-temperature -20)
REDICULOUSLY-COLD

CL-USER 48 : 7 >

;;; (case <key form> (key1 실행문들> ... <otherwise 실행문>)
;;;; (case <key form>
;;;;          (<key 1> <cosequnce 1-1> ...)
;;;;          (<key 2> <cosequnce 2-1> ...)
;;;;              ....
;;;;          (<key n> <cosequnce n-1> ...))
;- key form과 key들을 eq가 아닌 eql로 비교하여 매치되면 해당 절을 실행
;- Nil 반환값을 막기 위해 마지막 절을 t 또는 otherwise로 시작

CL-USER 40 : 7 > (setf thing 'point r 1)
1

CL-USER 41 : 7 > (case thing
                                  (circle (* pi r r))
                                  (sphere (* 4 pi r r))
                                  (t 0))
0

CL-USER 42 : 7 > (setf thing 'ball r 1)
1

CL-USER 43 : 7 > (case thing
                                  ((circle wheal) (* pi r r))
                                  ((sphere ball) (* 4 pi r r))
                                  (otherwise 0))
12.566370614359173D0


;;; 단계적으로 problem reduction 기법을 이용하여라
CL-USER 48 : 7 > (defun both-ends (whole-list)
                   (case (length whole-list)
                     (0 nil)
                     (1 (cons (first whole-list) whole-list))
                     (2 whole-list)
                     (t (cons (first whole-list) (last whole-list)))))
BOTH-ENDS

CL-USER 49 : 7 > (both-ends '(a c e f a k))
(A K)



;;; (and (조건1) (조건2) (조건3) ... (조건n))
;- 조건 중 어느 것 하나라도 처음에 거짓이면 더 이상 진행 않는다. >> Nil
;- 모든 조건이 참이이면 제일 마지막 반환값을 반환한다.
;- Nil이 아닌 반환값을 반환할 때는 모든 조건이 참이었음을 알 수 있다.

;;; (or (조건1) (조건2) (조건3) ... (조건n))
;- 조건 중 처음 어느 것 하나라도 참이면 더 이상 진행 않는다. >> 그 참인 것의 반환값
;- 모든 조건이 거젓이이면 >> Nil
;- Nil이 아닌 반환값을 반환할 때는 적어도 하나가 참이었음을 알 수 있다.

;;; (not (조건))
;- 존재의 유무 확인 또는 명제의 역
;- 단순히 notNil한 변수에 대하여 Nil을, Nil을 T로 전한하는 역할 수행
;- 논리적인 관계를 다루며, 리스트에서 이에 상응하는 것은 null 이다.
;- 반환값은 2가지 뿐 T / Nil


;;;; Predicates ;;;;;;
;- 참 또는 거짓만을 반환하는 procedure
;- 반한값이 t 또는 nil

null        ;;; 원래 빈 리스트인가? data type test
endp       ;;; 리스트가 다 비었는가? btter

listp        ;;; 리스트인가?
atom       ;;; 아톰인가?

symbolp ;;; 문자인가?
numberp
;;; 숫자인가?

integerp
 ;;; 문자인가?
ratiop      ;;; 문자인가?
floatp
       ;;; 문자인가?

zerop     ;;; 0인가?
minusp  ;;; 음수인가?
plusp     ;;; 양수인가?

evenp    ;;; 짝수인가?
oddp     ;;; 홀수인가?

>
          ;;; 점점 작아지는가? 내림차순으로 배열되어 있는가?
<          ;;; 점점 커지는가? 오름차순으로 배열되어 있는가?


         ;;; same number? / effcient
eq        ;;; same symboll? / efficient
eql       ;;; same typed number or symbol? /efficient
equal    ;;; same expression?  / for ATOM or LIST / expensive



CL-USER 1 > (setf pairs '((maple shade) (apple fruit)))
((MAPLE SHADE) (APPLE FRUIT))

CL-USER 2 > (member 'maple pairs)   ;;; member는 eql을 기본으로 하여 체크
NIL

CL-USER 3 > (member '(maple shade) pairs)  ;;; 타입이 맞지 않으므로 조정해줘야 함.
NIL

CL-USER 4 > (member '(maple shade) pairs :test #'equal) ;;eql 아닌 equal을 이용해서
((MAPLE SHADE) (APPLE FRUIT))    ;;;; member의 키워드는 :test, :test-not, :key


CL-USER 5 > (member '(maple shade) pairs :test-not #'equal)
((APPLE FRUIT))                      ;;; :test 결과물 중 자신이 아닌 나머지를 보여줌.



CL-USER 29 : 6 > (setf one 1 two 2 three 3 four 4)
4

CL-USER 30 : 6 > (setf digits (list one two three four))
(1 2 3 4)

CL-USER 31 : 6 > digits  ;;;; variable
(1 2 3 4)

CL-USER 32 : 6 > 'digits  ;;; symbol
DIGITS