<< Previous exercise (2.21) | Index | Next exercise (2.23) >>
Saying in a different way, the bug on the second version can also be attributed to the property of cons as shown below.
1 ]=> (cons 1 2) ;Value 11: (1 . 2) 1 ]=> (cons 1 (list 2 3)) ;Value 12: (1 2 3) 1 ]=> (cons (list 2 3) 1) ;Value 13: ((2 3) . 1)
We can also find that the 2nd will have nil as the 1st item of the result structure instead of the square of the 1st item of the input list. So it is wrong.
---
When I continued reading this page, The above is same as Tengs's comment.
An implementation evolving an iterative process works.
(define (square-list items)
(define (iter l pick)
(define r (square (car l)))
(if (null? (cdr l))
(pick (list r))
(iter (cdr l) (lambda (x) (pick (cons r x))))))
(iter items (lambda (x) x)))
An innovative solution. Please consider, from a tyro, the following polish which doesn't fail on the empty list.
(define (square-list5 items)
(define (iter l pick)
(if (null? l)
(pick l)
(let ((r (square (car l))))
(iter (cdr l) (lambda (x) (pick (cons r x)))))))
(iter items (lambda (x) x)))
Compared with the 1st code in the exercise, here somarl's implementation delays the cons using lambda until the final item of the input list (Think that from the 3rd call iter inclusive, each call of pick in (lambda (x) (pick (cons r x))) does something like adding one wrapper (cons r ...) where r depends on the last iteration). So it does something like (cons a (cons b (cons c ... (cons z '())...))) where a means the 1st item and others are similar. The exercise 1st code doesn't delay and does (cons z (cons y (cons x ... (cons a '())...))).
---
Also see mueen's comment in sicp-ex-2.20 which is same as roy-tobin's allowing rest to be nil.
the problem here is that Louis uses iteration and now we can only use cdr to get the rest of the list, so we must process the list from the tail by iteration, and since the answer is originally nil, we can't just change the order to (cons answer (square (car things))) because when the program executed to the innermost iteration, the first element will be nil, so the result will be like (((() . 1) . 4) . 9)
jz