CSC 153 Grinnell College Spring, 2005
Computer Science Fundamentals
Laboratory Exercise

Local Bindings


This laboratory exercise explores three new, but related, mechanisms to associate values with variables:


  1. What are the values of the following let-expressions?

    1. (let ((tone "fa") (call-me "al"))
        (string-append call-me tone "l" tone))
    2. ;; solving the quadratic equation x^2 - 5x + 4
      (let ((discriminant (- (* -5 -5) (* 4 1 4))))
        (list (/ (+ (- -5) (sqrt discriminant)) (* 2 1))
              (/ (- (- -5) (sqrt discriminant)) (* 2 1))))
    3. (let ((sum (+ 8 3 4 2 7)))
        (let ((mean (/ sum 5)))
          (* mean mean)))

    You may use Chez Scheme to help you answer these questions, but be sure you can explain how it arrived at its answers.

  2. Consider the following count-all-symbols procedure which counts the number of symbols that appear in a list or any of its sublists. A sample run also is given:

    (define count-all-symbols
      (lambda (ls)
      ;Pre-condition:  ls is a list
      ;Post-condition:  returns the number of symbols on ls or any sublist of ls
        (cond ((null? ls) 0)
              ((symbol? (car ls)) (+ 1 (count-all-symbols (cdr ls))))
              ((list? (car ls))
               (+ (count-all-symbols (car ls)) (count-all-symbols (cdr ls))))
              (else (count-all-symbols (cdr ls))))))
    (count-all-symbols '(((a b) c) d (e (f)))) ===> 6

    Rewrite this count-all-symbols procedure, using a let-expression to consolidate repeated subexpressions in the same manner.


  1. Write a nested let-expression that binds a total of five variables, a, b, c, d, and e, with a bound to 9387 and each subsequent variable bound to a value twice as large as the one before it -- b should be twice as large as a, c twice as large as b, and so on. The body of the innermost let-expression should compute the sum of the values of the five variables.

  2. Write a let*-expression equivalent to the let-expression in the previous exercise.

  3. Rewrite the longest-on-list procedure from the first lab on recursion so that it incorporates the longer-string procedure by means of a local binding.


  1. Write a letrec-expression in which (a) the identifier last-of-list is locally bound to a procedure that finds and returns the last element of a given list, and (b) the body of the expression computes the sum of the last elements of the lists (3 8 2), (7), and (8 5 9 8), invoking last-of-list three times.

The letrec-expression makes it possible to include binding specifications for mutually recursive procedures in the same binding list:

(letrec ((up-sum
          (lambda (ls)
            (if (null? ls)
                (+ (down-sum (cdr ls)) (car ls)))))
          (lambda (ls)
            (if (null? ls)
                (- (up-sum (cdr ls)) (car ls))))))
  (up-sum '(1 23 6 12 7))
===> -21
  1. 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.

    Using the letrec definitions of up-sum and down-sum as an example, write a letrec-expression in which (a) the identifiers s-n-alternator? and n-s-alternator? are bound to mutually recursive predicates, each of which determines whether a given non-empty list has the indicated characteristic, and (b) the body invokes each of these predicates to determine whether the list (2 a 3 b 4 c 5) fits either description.

This document is available on the World Wide Web as

created February 26, 1997
last revised February 1, 2005
Valid HTML 4.01! Valid CSS!
For more information, please contact Henry M. Walker at