2017-03-06 9 views
0

誰かが以下の理由で動作しない理由を説明できますか?私はSICPを通過しています。この演習では、構造のペアを数える関数を作成する必要があります。このプログラムは3つの構造で使用され、すべてが3つのペアで構成されています。SICP ex 3.17 - カウントペア - 私の答えが間違っている理由がわかりません

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

正しい解決方法を以下に示します。何がうまくいかないでしょうか?私は、遭遇した人が少し違った扱いを受けていることに気付いていますが、何がうまくいかないのか分かりません。

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

入力(l1とy1)は以下に示されていますが、試してみる必要はありません。

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

答えて

1

答えでは、encounteredがヘルパーに引数としてあります。つまり、helperを使用するたびに、encounterという独自のバージョンが使用されます。このフォーム読んだとき:

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

をあなたはヘルパーを持っているので、コードは再びヘルパーを行うことを再開したとき、それは同じバージョンを渡すことをバインディングに追加しますので、第二の再帰は、追加が最初で行われていません。最初の再帰に渡されました。

ヘルパーが常に同じフリー変数を更新するようにletバインディングを設定すると、バインディングのいくつかのバージョンが存在しないようになります。

関連する問題