2013-10-06 80 views
0

有人可以向我解釋遞歸如何在以下函數中工作嗎?具體來說,我感興趣的是當函數達到基本情況時會發生什麼。另外,爲什麼在這段代碼中使用了一個命名的let? (我不熟悉的命名讓)計劃車和cdr遞歸

(define (unzip list-of-pairs) 
    (if (null? list-of-pairs) 
    (cons '() '()) 
    (let ((unzipped (unzip (cdr list-of-pairs)))) 
     (cons (cons (car (car list-of-pairs)) (car unzipped)) 
       (cons (cdr (car list-of-pairs)) (cdr unzipped)))))) 

回答

1

表示沒有什麼特別的關於它的過程中,你只是遍歷這種形式的列表:

'((1 . 2) (3 . 4) (5 . 6)) 

唯一的「奇怪「的一部分是,輸出是建立兩個列表,而不是通常的單一列表。如你所知,我們正在構建一個列表作爲輸出的基本情況是這樣的:

(if (null? lst) '() ...) 

但在這裏,因爲我們同時建設兩個名單,基本情況是這樣的:

(if (null? lst) (cons '() '()) ...) 

問題中的代碼沒有使用named let,它只是一個普通的舊花園品種let,沒有什麼特別的。這很有用,因爲我們只需要調用遞歸一次,因爲我們需要從遞歸調用中獲取兩個值。

如果我們不介意效率低下,程序可以不使用let寫的,在調用遞歸兩次在每一步的成本:

(define (unzip list-of-pairs) 
    (if (null? list-of-pairs) 
     (cons '() '()) 
     (cons (cons (car (car list-of-pairs)) 
        (car (unzip (cdr list-of-pairs)))) 
      (cons (cdr (car list-of-pairs)) 
        (cdr (unzip (cdr list-of-pairs))))))) 

當然,使用let的優勢它避免了雙重遞歸調用。

+0

也有一些可疑的實施。例如。嘗試'(unzip'((a b c)(1 2 3))); ==((a 1)(bc)(2 3))' – Sylwester

+0

@Sylwester輸入對於過程是錯誤的,它需要一個_pairs_的列表,例如:''((1。2)(3。 4)(5.6))' –

+0

所以它不是(un)zip,而是遞歸版本'(cons(map car lst)(map cdr lst))'。得到它了 :) – Sylwester