데이터, 조건, 결정

인용 데이터와 if와 cond와 단락 평가를 써서 결정을 리스트로 반환합니다.

조건에 따라 결정을 고르고 리스트로 반환하는 코드를 작성합니다. if, and, or, cond가 어느 식을 평가할지도 예상해 봅니다.

코드가 곧 데이터를 먼저 읽으세요. 각 예제는 플레이그라운드에서 따로 실행해 결과를 확인하세요.

인용으로 데이터 남기기

LISPEX
(+ 1 2)

결과

출력
3

이 식은 +를 호출합니다. 인용하면 리스트를 데이터로 반환합니다.

LISPEX
'(+ 1 2)

결과

출력
(+ 1 2)

고정된 데이터에는 quote를 쓰세요. 인자들을 평가한 값으로 리스트를 만들 때는 list를 쓰세요.

LISPEX
(list 'decision 'keep)

결과

출력
(decision keep)

여기서는 두 인자가 각각 심볼을 반환합니다. 앞 수업처럼 원소의 값을 계산하는 식을 전달할 수도 있습니다.

if로 두 결과 중 하나 고르기

LISPEX
(if (< 1 2)
    '(decision next-page)
    '(decision keep))

결과

출력
(decision next-page)

if 뒤에는 검사할 식과 참일 때의 식, 거짓일 때의 식이 옵니다. 남은 1줄이 2줄보다 적으므로 '(decision next-page)를 고릅니다. 고른 분기만 평가합니다.

#f만 거짓입니다. 수 0, 빈 문자열 "", 빈 리스트 ()는 모두 참으로 취급합니다. 수가 양수인지, 리스트가 비었는지 확인하려면 술어를 쓰세요. 술어는 #t나 #f를 반환하는 프로시저입니다.

and와 or로 일찍 멈추기

LISPEX
(and (> 5 1)
     (not #f))

결과

출력
#t

(> 5 1)가 #t를 반환하므로 and는 (not #f)도 평가합니다. 그 결과도 #t입니다. not은 #f를 받으면 #t를, 그 밖의 값을 받으면 #f를 반환합니다.

and는 왼쪽부터 식을 평가하다가 첫 #f에서 멈춥니다. or도 왼쪽부터 평가하지만 #f가 아닌 첫 값에서 멈춥니다. 뒤의 식들은 평가하지 않습니다. 이를 단락 평가라고 합니다.

LISPEX
(or #f 'standard)

결과

출력
standard

or는 #f를 지나 심볼 standard를 반환합니다. 인자가 있는 and와 or는 멈춘 자리의 값을 그대로 반환합니다. 일찍 멈추지 않으면 마지막 인자의 값을 반환합니다. 이 값을 불리언으로 바꾸지는 않습니다.

cond로 여러 경우 중 하나 고르기

LISPEX
(define (heading-decision lines-left chapter-heading?)
  (cond
    ((< lines-left 2) '(decision next-page))
    (chapter-heading? '(decision new-chapter))
    (else '(decision keep))))

(heading-decision 5 #t)

결과

출력
(decision new-chapter)

cond는 위에서 아래로 검사합니다. 5줄이 남았으므로 첫 검사는 거짓입니다. 장 제목 여부가 참이므로 new-chapter를 고릅니다. 2줄보다 적게 남았으면 먼저 next-page를 고릅니다. 두 검사 모두 거짓이면 else에서 keep을 고릅니다. 심볼 decision은 답의 종류를 나타냅니다.

리스트 살펴보기

LISPEX
(define answer '(decision keep))
(list (car answer) (car (cdr answer)))

결과

출력
(decision keep)

비어 있지 않은 리스트에서 car는 첫 원소를, cdr은 나머지 리스트를 반환합니다. 여기서 (car answer)는 decision을 반환합니다. (car (cdr answer))는 keep를 반환합니다. list가 두 값을 다시 묶습니다.

규칙을 작성할 때는 가능하면 결과를 직접 만드세요. 리스트의 같은 부분을 반복해서 꺼낸다면, 그 작업에 이름을 붙인 프로시저로 코드를 읽기 쉽게 만들 수 있습니다.

연습

여백이 18mm 이상이면 그대로 두고 더 작으면 넓히는 margin-decision을 작성하세요.

답 하나 보기
LISPEX
(define (margin-decision margin-mm)
  (if (>= margin-mm 18)
      '(decision keep)
      '(decision widen narrow-margin)))

(margin-decision 17)

결과는 (decision widen narrow-margin)입니다.

'(decision keep)와 (decision keep)의 차이를 설명하고 if의 세 부분을 짚어 보세요. 첫 결정 규칙에서 배운 내용을 하나의 규칙으로 묶습니다.