Local binding and recursion

Exercise 1

Fill in the definition of the local procedure last-of-list into the letrec expression below.

(letrec ((last-of-list



              ))
    (+ (last-of-list '(3 1 4)) (last-of-list '(7)) (last-of-list
'(9 10))))

Exercise 2

A non-empty list is an s-n-alternator if its elements are alternately symbols and numbers, beginning with a symbol. It is an n-s-alternator if its elements are alternately numbers and symbols, beginning with a number.

Fill in the mutually recursive definitions of s-n-alternator? and n-s-alternator? into the letrec expression in the procedure below.


(define alternator
  (lambda (ls)
    (letrec ((s-n-alternator?




             )
             (n-s-alternator?




             ))
        (cond
          ((s-n-alternator? ls) "s-n-alternator")
          ((n-s-alternator? ls) "n-s-alternator")
          (else "neither")))))

Test the completed procedure with lists '(2 a 3 b 4 c 5), '(a 3 b 4 c 5), and '(2 a 3 b 4 5).

Exercise 3

Define and test a tail recursive version of the iota procedure that uses letrec to pack a tail-recursive kernel inside a husk. (Iota, you'll recall, takes a natural number as argument and returns a list of all the lesser natural numbers, in ascending order.)

Exercise 4

Define and test a tail-recursive version of the iota procedure that uses a named let.

Exercise 5

Define and test a tail-recursive version of the factorial procedure that uses a named let.

Exercise 6

Define and test a tail-recursive version of the Fibonacci procedure that uses a named let.
(Recall that another Fibonacci procedure was discussed previously in the reading on tail recursion.)

Exercise 7

Define and test a procedure named take that takes a list ls and a non-negative integer len as arguments and returns a list consisting of the first len elements of ls, in their original order. The procedure should signal an error if ls is not a list, if len is not an exact integer, if len is negative, or if len is greater than the length of ls. In this case you should place the recrusive procedure that does the work in the letrec, and do the error checking outside of the letrec in the main procedure. (Tail recursion is not recommended here).

Exercise 8

Define and test a procedure named intersection that takes two lists of symbols, left and right, as arguments and returns a list of which the elements are precisely those symbols that are elements of both left and right. Hint: use element? in the letrec.

Exercise 9

Define and test a tail-recursive version of the deep-reverse procedure that uses a letrec.

Exercise 10

Define and test a procedure called partition which takes as input a number num and a list of numbers ls, and returns a list of two lists: less, which contains all elements of ls that are less than num, and greater, which contains all elements of ls that are greater than num. For example, (partition '(31 41 59 65 35) 50) might return ((35 41 31) (65 59)). Note that the order of the elements inside less and greater does not matter.


This document is available on the World Wide Web as

http://www.cs.grinnell.edu/~gum/courses/151/labs/local-binding-and-recursion.xhtml

created March 2, 1997
last revised June 23, 2003

John David Stone (stone@cs.grinnell.edu) and Ben Gum (gum@cs.grinnell.edu)