20-CS-4003-001 Organization of Programming Languages Fall 2017
Tail Recursion

Lambda calculus, Type theory, Formal semantics, Program analysis

    Prev     Next     All lectures        Code

Tail Recursion Example

(define merge
  (lambda (x y)
    (if (null? x) 
        y
        (if (null? y)
            x 
            (if (< (car x) (car y))
                (cons (car x) (merge (cdr x) y))
                (cons (car y) (merge (cdr y) x)))))))

(define test1 
  (let ((x '(3 6 7 12 24 56 57 78)) 
        (y '(1 2 11 56 66 68 71)))
    (merge x y)))

;; invariant: acc is the merge of x and y tokens seen
;;         before the current invocation of merge_acc
(define merge_acc
  (lambda (x y acc)
    (if (null? x)
        (append acc y)
        (if (null? y)
            (append acc x)
            (if (< (car x) (car y))
                (merge_acc
                  (cdr x)
                  y
                  (append acc (list (car x))))
                (merge_acc
                  (cdr y)
                  x
                  (append acc (list (car y)))))))))

(define test2
  (let ((x '(3 6 7 12 24 56 57 78)) 
        (y '(1 2 11 56 66 68 71)))
    (merge_acc x y '())))
 -  The function merge takes two non-decreasing lists of numbers as input and outputs all numbers in those lists in non-decreasing order. The function is not tail recursive. The function merge_acc is tail recursive. The invariant is: acc is the merge of x and y numbers seen before the current invocation of merge_acc. The invariant holds on every call because only elements of x and y are appended to acc and each element that is appended is not less than any in acc (guaranteed by the assumption that x and y are in non-decreasing order).