sicp-ex-2.22



<< Previous exercise (2.21) | Index | Next exercise (2.23) >>


jz

  
 (define nil '()) 
  
 (define (square-list items) 
   (define (iter things answer) 
     (if (null? things) 
         answer 
         (iter (cdr things) 
               (cons (square (car things)) answer)))) 
   (iter items nil)) 
  
 (square-list (list 1 2 3 4)) 
  
 ;; The above doesn't work because it conses the last item from the 
 ;; front of the list to the answer, then gets the next item from the 
 ;; front, etc. 
  
 (define (square-list items) 
   (define (iter things answer) 
     (if (null? things) 
         answer 
         (iter (cdr things) 
               (cons answer (square (car things)))))) 
   (iter items nil)) 
  
 (square-list (list 1 2 3 4)) 
  
 ;; This new-and-not-improved version conses the answer to the squared 
 ;; value, but the answer is a list, so you'll end up with (list (list 
 ;; ...) lastest-square). 
  

shyam

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)


somarl

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))) 


Tengs

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)