0

Can someone explain why the below doesn't work? I'm going through SICP. This exercise wants you to make a function that counts the pairs of a structure. The program is used on three structures, all with three pairs.

(define (count-pairs x)
  (define (helper x encountered) 
    (if (or (not (pair? x)) (memq x encountered))  
        0
        (begin
          (set! encountered (cons x encountered))
          (+ (helper (car x) encountered)
             (helper (cdr x) encountered)
             1))))

  (helper x (list)))

The correct solution is shown below. What could be going wrong? I notice that encountered is handled slightly differently but I don't see what could go wrong.

(define (count-pairs x)
  (let ((encountered '())) 
    (define (helper x) 
      (if (or (not (pair? x)) (memq x encountered)) 
          0 
          (begin 
            (set! encountered (cons x encountered)) 
            (+ (helper (car x)) 
               (helper (cdr x)) 
               1))))

    (helper x))) 

The inputs (l1 and y1) are shown below but you don't have to try it out.

; 4 pairs counted with wrong way, 3 with correct way
(define l1 (list 1 2))
(define l2 (list 3))
(set-car! l1 l2)
(set-cdr! l2 (cdr l1))

; 7 pairs counted with the wrong way, 3 with correct way
(define y1 (list 1))
(define y2 (list 1))
(define y3 (list 1))
(set-car! y1 y2)
(set-cdr! y1 y2)
(set-car! y2 y3)
(set-cdr! y2 y3)
Sylwester
  • 47,942
  • 4
  • 47
  • 79
user12858
  • 3
  • 1

1 Answers1

1

In your answer you have encountered as an argument in the helper. That means that every use of helper will have its own version of encounter. When you read this form:

(+ (helper (car x) encountered)
   (helper (cdr x) encountered)
   1)

The second recursion will not have the additions done by the first since you add to the binding that helper has and thus when the code resumes to do the helper again it passes the same version it passed to the first recursion.

By having a let binding such that he helper always updates the same free variable you avoid that several versions of the binding exists.

Sylwester
  • 47,942
  • 4
  • 47
  • 79