I'm doing the exercises from SICP (not homework) and exercise 2.20 introduces dotted-tail notation, which is where you use (define (f a . b) ...)
to pass a variable number of arguments (which end up in a list b
). This problem in particular wants a procedure which takes an integer a
and returns a list of all arguments with parity equal to a
's. The problem is not difficult; here is my solution:
(define (same-parity a . b); a is an int, b is any number of int arguments
(let ((parity (remainder a 2)))
(define (proc li)
(cond ((null? li) null)
; If parity of the head of the list is = parity of a,
((= (remainder (car li) 2) parity)
; keep it and check the rest of the list.
(cons (car li) (proc (cdr li))))
; Otherwise ignore it and check the rest of the list.
(else (proc (cdr li)))))
(cons a (proc b))))
My question is that I don't seem to be using the dotted-tail feature at all. I might as well have just accepted exactly two arguments, a number and a list; I'm effectively wrapping the algorithm in a procedure proc
which does away with the dotted-tail thing.
Before I wrote this solution, I wanted to have a recursive call resembling
(same-parity a . (cdr b))
or something spiritually similar, but no matter how I tried it, I kept passing lists of lists or extra procedures or whatever. This could be because I don't know exactly what .
does, only what I want it to do (the Racket docs didn't clear anything up either). To sum up,
Is my solution what was intended for this exercise, or is there a way to actually use the dot notation (which seems to be the point of the exercise) in the algorithm?
You can't use (same-parity a . (cdr b))
(since that would be read in as (same-parity a cdr b)
), but you can use (apply same-parity a (cdr b))
. That's how you "splat" a list into arguments.
However, the "inner procedure" approach you had is generally more efficient, as there is less list copying going on.