SICP 연습문제 2.20 친절한 풀이

문제

+,*,list같은 프로시저에서는 인자의 수가 정해지지 않는다. 그런 프로시저를 정의하는 방법 가운데 하나는, 꼬리점 문법dotted-tail notation을 쓰는 것이다. 이 문법으로 프로시저를 정의할 때에는, 마지막 인자 이름 앞에 '.'이 찍힌 인자 리스트를 받는다. 이때 이 문법이 뜻하는 바는, 이렇게 정의된 프로시저를 불러 썼을 때, 첫 번째 인자parameter는 다른 프로시저와 다를 바 없이 첫 번째 인자 값argument으로 맞바뀐다는 것이다. 그러나 마지막 인자는 남아 있는 인자들의 리스트가 된다. 그 보기로, 다음과 같은 프로시저 정의가 있다고 하자.

(define (f x y . z) <body>)

프로시저 f는 인자를 두 개 이상 받을 수 있다.

(f 1 2 3 4 5 6)(f \ 1 \ 2 \ 3 \ 4 \ 5 \ 6)

이 경우에, f의 몸에서 x는 1로, y는 2로, z는 리스트 (3 4 5 6)의 값으로 맞바뀐다. 또, 다음과 같은 정의가 있다고 하자.

(define (g . w) <body>)

이때, 프로시저 g는 인자를 0개 이상으로 받을 수 있다.

(g 1 2 3 4 5 6)(g \ 1 \ 2 \ 3 \ 4 \ 5 \ 6)

g의 몸에서 w는 리스트 (1 2 3 4 5 6)의 값을 받는다.
이 문법을 써서, 하나 이상의 정수를 인자로 받아, 첫 번째 인자가 짝수라면 짝수 원소만, 홀수라면 홀수 원소만 들어 있는 리스트를 결과로 내놓는 프로시저 same-parity를 짜보라. 이 프로시저에 다음 인자 값을 건네어 계산하면, 그 아래에 있는 결과가 나온다.

(same-parity 1 2 3 4 5 6 7)
>> (1 3 5 7)

문제로 부터 얻은 것

여러 인자를 받는 프로시저를 정의할 수 있는 방법을 배웠습니다.
iter를 이용해서 리스트를 만들때 받은 순서대로 만드는 방법과, 그 반대로 만드는 방법을 둘 다 사용해볼 수 있었습니다.

문제풀이

저는 내부적으로 되도는 프로시저를 구현할 때, 홀수인지 짝수인지 결정하는 프로시저 even?과 odd?를 인자로 넘겨주어 사용했습니다. 지금 생각해보니, filter 프로시저를 사용해서 구현하는 것도 좋은 방법같습니다.

(define (same-parity a . b)
(define (list-iter term x)
(if (null? x)
nil
(if (term (car x))
(cons (car x) (list-iter term (cdr x)))
(list-iter term (cdr x)))))

(if (even? a)
(cons a (list-iter even? b))
(cons a (list-iter odd? b))))



아래의 테스트 코드를 사용해서 프로시저를 테스트해 보았습니다.

(same-parity 1 2 3 4 5 6 7 9)
(same-parity 2 3 4 5 6 7 9 10)

홀수 리스트와 짝수 리스트를 출력하는 모습



filter를 사용해서 한번 구현해 보았습니다. 아래의 filter 프로시저는 책의 151p에 있습니다.

(define (filter predicate sequence)
(cond ((null? sequence) nil)
((predicate (car sequence))
(cons (car sequence) (filter predicate (cdr sequence))))
(else (filter predicate (cdr sequence)))))

(define (same-parity a . b)
(if (even? a)
(cons a (filter even? b))
(cons a (filter odd? b))))

동일하게 홀수 리스트와 짝수 리스트를 출력하는 모습



읽어주셔서 감사합니다.