2013-10-06 56 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