20-CS-4003-001 Organization of Programming Languages Fall 2017
Miscellaneous Ideas

Lambda calculus, Type theory, Formal semantics, Program analysis

    Prev     Next     All lectures        Code

Tail Recursion

;; (build4 1000000) -> out of memory
(define build4
  (lambda (n)
    (letrec 
      ((build 
         (lambda (n acc)
           (if (zero? n)
               acc
               (build (- n 1) (cons n acc))))))
      (build n '()))))

;; (build1 1000000) -> abort stack limit
(define build1 
  (lambda (n)
    (if (zero? n)
        '()
        (cons n (build1 (- n 1))))))

;; requires a stack
(define fib1
  (lambda (n)
    (letrec 
      ((fib
         (lambda (n x y)
           (if (zero? n)
               '()
               (cons (+ x y) 
                     (fib (- n 1) (+ x y) x))))))
      (fib n 1 1))))

;; tail recursive
(define fib2
  (lambda (n)
    (letrec 
      ((fib
         (lambda (n x y acc)
           (if (zero? n)
               acc
               (fib (- n 1) 
                    (+ x y) 
                    x 
                    (cons (+ x y) acc))))))
      (fib n 1 1 '()))))

;; tail recursive
(define fib3
  (lambda (n)
    (letrec 
      ((fib
         (lambda (n x y)
           (if (zero? n)
               x
               (fib (- n 1) (+ x y) x)))))
      (fib n 1 1))))

;; factorial - (fact1 100000) aborts on stack depth
(define fact1
  (lambda (n)
    (if (= n 1)
        1
        (* n (fact1 (- n 1))))))

;; factorial with tail recursion - (fact2 100000)
;; - runs for awhile
(define fact2
  (lambda (n)
    (letrec 
      ((fact
         (lambda (n acc)
           (if (= n 1)
               acc
               (fact (- n 1) (* n acc))))))
      (fact n 1))))

;; (findmax1 (build4 1000000)) -> abort
(define findmax1
  (lambda (lst) 
    (if (null? lst)
        '()
        (if (null? (cdr lst))
            (car lst)
            (max (car lst) 
                 (findmax1 (cdr lst)))))))

;; (findmax2 (build4 1000000)) -> solves
(define findmax2
  (lambda (lst)
    (letrec 
      ((findmax
         (lambda (lst acc)
           (if (null? lst)
               acc
               (findmax (cdr lst) 
                        (max acc (car lst)))))))
      (if (null? lst)
          '()
          (findmax (cdr lst) (car lst))))))

 -  The function build4 from the previous slide is tail recursive. This means putting recursive calls on a stack is unnecessary because there are no operations to return to. On the other hand, build1 is not tail recursive due to the need to return from the call to (build1 (- n 1)) to do a cons. Running (build1 1000000) quickly aborts due to reaching the limit of stack depth. However, (build4 1000000) aborts with an out of memory error - there is not enough memory to make the list.

The function fib1 is not tail recursive but the function fib2 is tail recursive. Both produce a list of fibonacci numbers. Function fib3 produces the nth fibonacci number and is tail recursive.

Additional examples are shown.