데이터, 조건, 결정

심볼과 리스트를 데이터로 남기고, `if`와 `cond`로 답 하나를 고르고, 단락 평가와 이름 붙은 결정값까지 익힙니다.

프로그램이 유용하려면 코드와 데이터를 구분하고 결과 하나를 골라야 합니다. 리스펙스는 이 두 가지를 코드에 그대로 드러냅니다. 인용은 데이터를 보존하고, 조건식은 어느 식을 평가할지 고릅니다.

인용은 폼을 데이터로 둡니다

인용하지 않으면 리스펙스는 비어 있지 않은 리스트를 평가할 대상으로 봅니다.

LISPEX
(+ 1 2)

인용하면 리스펙스는 같은 모양을 데이터로 돌려줍니다.

LISPEX
'(+ 1 2)

결과

OUTPUT
(+ 1 2)

평가한 값으로 새 리스트를 만들 수도 있습니다.

LISPEX
(list 'decision 'allow)

결과

OUTPUT
(decision allow)

값이 고정된 리터럴 데이터에는 인용을 쓰세요. 원소 가운데 계산해야 할 것이 있으면 list를 쓰세요.

if는 둘 중 하나를 고릅니다

if에는 검사, 참일 때의 결과, 거짓일 때의 결과가 있습니다.

LISPEX
(if (>= 62 50)
    '(decision free-shipping)
    '(decision standard-shipping))

고른 가지 하나만 실행됩니다. #f만 거짓이고 0, "", ()는 모두 참입니다. 비어 있지 않다거나 양수라는 뜻이 필요하면 그 뜻에 맞는 술어를 직접 쓰세요.

andor는 일찍 멈춥니다

and는 왼쪽부터 차례로 평가하다가 #f를 만나면 멈춥니다. or는 처음 만난 참 값에서 멈춥니다.

LISPEX
(and (<= 9 14)
     (not #f))

결과

OUTPUT
#t

결과가 이미 정해지면 오른쪽 식은 평가하지 않습니다. 이렇게 일찍 멈추는 동작도 평가 규칙의 일부입니다.

cond는 여러 경우에 이름을 붙입니다

LISPEX
(define (shipping-decision total member?)
  (cond
    ((>= total 50) '(decision free-shipping))
    (member? '(decision discounted-shipping))
    (else '(decision standard-shipping))))

(shipping-decision 42 #t)

결과

OUTPUT
(decision discounted-shipping)

절을 위에서 아래로 차례로 검사합니다. 총액이 충분하면 회원 여부보다 먼저 무료 배송을 고릅니다. else는 마지막 기본값입니다. 이름을 붙인 리스트는 이 프로시저를 모르는 사람에게도 답이 무슨 뜻인지 알려 줍니다.

필요할 때 리스트 살펴보기

올바른 리스트에서 car는 첫 값을 반환하고, cdr은 나머지 리스트를 반환합니다.

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

결과

OUTPUT
(decision allow)

보통 규칙에서는 직접 만드는 방식과 술어를 쓰세요. carcdr을 이어 붙이는 방식은 학습할 때나 낮은 수준으로 접근할 때 유용하지만, 이름 붙인 도우미가 의도를 더 잘 보여 주는 경우가 많습니다.

연습

18세 이상이면 (decision allow)를 반환하고, 그보다 어리면 (decision deny under-age)를 반환합니다. 이렇게 동작하는 age-decision을 작성하세요.

답 하나 보기
LISPEX
(define (age-decision age)
  (if (>= age 18)
      '(decision allow)
      '(decision deny under-age)))

(age-decision 17)

결과는 (decision deny under-age)입니다.

4단계로 갈 준비가 됐나요?

'(decision allow)(decision allow)의 차이, if의 세 위치, 0이 거짓이 아닌 이유를 설명할 수 있으면 다음으로 넘어가도 좋습니다. 다음은 첫 결정 규칙입니다.