CS 357 : Declarative Programming

Homework 5 (Spring 2009)

  1. Write a function, curry-skip, with the following behavior:
    > ((curry-skip 0) 'foo)
    foo
    > (((curry-skip 1) 'foo) 'bar)
    bar
    > ((((curry-skip 2) 'foo) 'bar) 'baz)
    baz
    >
    
  2. Write make-lookup-function which takes as arguments: 1) A symbol, target; and 2) An s-expression, sexpr, to be searched. make-lookup-function returns a function composed of car's and cdr's that will fetch target out of sexpr. If target is not found in sexpr, make-lookup-function returns #f. If target appears more than once, the returned function should access the first occurence of target (as printed). > (define foo (make-lookup-function 'd '(a (b c (d e) f g) h))) > (foo '(a (b c (d e) f g) h)) d > (foo '(1 (2 3 (4 5) 6 7) 8)) 4 > (define bar (make-lookup-function 'j '(a (b c (d e) f g) h))) #f > (define baz (make-lookup-function 'b 'b)) > (baz 'b) b > (baz 6) 6 >
  3. Declare a macro with keyword and, which may take any number of subexpressions. If called with no subexpressions, it evaluates to #t. If all of its subexpressions are not #f, it evaluates to the last one; otherwise it is #f.

  4. Many Scheme's have a special form called named-let which has the following abstract syntax:

    (let <name> ((<var1> <val1>)...(<varN> <valN>)) 
      <expr1>
      .
      .
      .
      <exprM>)
    
    =>
    ((letrec
      ((<name> 
        (lambda (<var1>...<varN>)
          <expr1>
          .
          .
          .
          <exprM>)))
        <name>) <val1>...<valN>)
    
    The named-let special form can be used as follows: >(let loop ((x 4) (acc 1)) (if (= x 1) acc (loop (- x 1) (* x acc)))) 24 > Use define-macro to define named-let.

  5. In the while special form, an expression is evaluated repeatedly as long as a given condition is true. We can achieve this effect in Scheme, without special syntax, as illustrated by the following program, which sums the numbers from 1 to 100: (let ((n 100) (sum 0)) (letrec ((loop (lambda () (if (positive? n) (begin (set! sum (+ sum n)) (set! n (sub1 n)) (loop)))))) (loop) sum)) However, for convenience, we would like to add a while special form, which would allow us to write the above program as: (let ((n 100) (sum 0)) (while (positive? n) (set! sum (+ sum n)) (set! n (sub1 n))) sum) and which has the following abstract syntax:
    (while <test> <expr1>...<exprN>)
    
    =>
    (letrec
      ((loop
        (lambda ()
          (if <test>
            (begin
              <expr1>
    	  .
    	  .
    	  .
    	  exprN>
    	  (loop))))))
      (loop))
    
    Define while using define-macro. Your definition must take into account the potential variable capturing that is caused when the variable loop occurs free in test or expression.

  6. Using the stream library defined in class, define the infinite stream of increasingly accurate Taylor series approximations for e:

    e(0) = 1/0! e(1) = 1/0! + 1/1! e(2) = 1/0! + 1/1! + 1/2! e(3) = 1/0! + 1/1! + 1/2! + 1/3!...

  7. The positive rational numbers, which are ratios of two positive integers, a/b, can be enumerated by listing them in order of increasing sums a+b, with those numbers having the same sum listed in order of increasing numerator a. Those fractions that are not in lowest terms are omitted from the enumeration. Thus, the enumeration begins with 1/1, 1/2, 2/1, 1/3, 3/1,... Define a stream, positive-rationals, that contains all of the positive rational numbers with numerator and denominator having no common divisor greater than one. Represent the rational number a/b as a list (a b) and use the Scheme procedure gcd to test whether a/b is in lowest terms. Test your program by listing the first twenty elements of the stream.