Explain the continuation example on p.137 of The Little Schemer

后端 未结 7 2026
清歌不尽
清歌不尽 2020-12-08 05:49

The code in question is this:

(define multirember&co
  (lambda (a lat col)
    (cond
     ((null? lat)
      (col (quote ()) (quote ())))
     ((eq? (car         


        
7条回答
  •  借酒劲吻你
    2020-12-08 06:16

    The code does not build the solution, as it happens usually, but it builds a code that computes the solution, exactly as when you would build the tree using low level operations, like cons, +, -, etc, instead of using high level accumulators or filters.

    This is why it is difficult to say if the process is iterative or recursive, because, by the definition of the iterative processes, they use a finite amount of memory for the local state. However, this kind of process uses much memory, but this is allocated in environment, not in local parameters.

    First, I duplicate the code here, to be able to see the correspondence without scrolling too much:

    (define multirember&co
      (lambda (a lat col)
        (cond
         ((null? lat)
          (col (quote ()) (quote ())))
         ((eq? (car lat) a)
          (multirember&co a
                          (cdr lat)
                          (lambda (newlat seen)
                            (col newlat
                                 (cons (car lat) seen)))))
         (else
          (multirember&co a
                          (cdr lat)
                          (lambda (newlat seen)
                            (col (cons (car lat) newlat)
                                 seen)))))))
    

    Let us try to split the problem to see what really happens.

    • Case 1:

    (multirember&co 'a
                    '()
                    (lambda (x y) (list x y)))
    
    is the same as    
    
    (let ((col (lambda (x y) (list x y))))
      (col '() '()))
    

    This is a trivial case, it never loops.

    Now the interesting cases:

    • Case 2:

    (multirember&co 'a
                    '(x)
                    (lambda (x y) (list x y)))
    
    is the same as    
    
    (let ((col
           (let ((col (lambda (x y) (list x y)))
                 (lat '(x))
                 (a 'a))
             (lambda (newlat seen)
               (col (cons (car lat) newlat)
                    seen)))))
      (col '() '()))
    

    In this case, the process produces this code as result, and finally evaluates it. Note that locally it is still tail-recursive, but globally it is a recursive process, and it requires memory not by allocating some data structure, but by having the evaluator allocate only environment frames. Each loop deepens the environment by adding 1 new frame.

    • Case 3

    (multirember&co 'a
                    '(a)
                    (lambda (x y) (list x y)))
    
    is the same as    
    
    (let ((col
           (let ((col (lambda (x y) (list x y)))
                 (lat '(a))
                 (a 'a))
             (lambda (newlat seen)
               (col newlat
                    (cons (car lat) seen))))))
      (col '() '()))
    

    This builds the code , but on the other branch, that accumulates a result in the other variable.


    All the other cases are combinations of 1 of these 3 cases, and it is clear how each 1 acts, by adding a new layer.

提交回复
热议问题