13 Lab Practice with Macros


define syntax functions

Exercise 23. Develop the compile-time function disjunction2 (without using or). The function deals with binary disjunctions of the shape

(disjunction2 lhs:expr rhs:expr)

After testing, run the expression (disjunction2 (displayln 1) (displayln 2)).

Stopbefore anyone continues, let’s discuss

Now generalize the function to disjunction, which deals with at least two but possibly an arbitrary number of expressions. image

Exercise 24. Develop the compile-time function block (without using let*). The function implements syntax of the shape

(block ((x1:id rhs1:expr) (x2:id rhs2:expr) ... (x3:id rhs3:expr)) body:expr)

The identifier x1 is visible in rhs2, but not vice versa, and so on. All x1 thru x3 are visible in body.

The evaluation initializes x1 to rhs1, x2 to rhs2, and so on. Once all identifiers are initialized, body is evaluated. image

Exercise 25. Develop the compile-time function for-loop. It realizes the following syntax trees as bounded loops over integers:

(for-loop ([i e0 limit]) body)


(for-loop ([i e0 limit stride]) body)

First, classify each piece of the input tree.

Second, develop the implementation for the second version only.

Third, add the first variant.

Fourth, explore what kind of error messages your implementation yields if the input tree does not match either pattern. image

Exercise 26. Develop the compile-time function while, which adds while-do loops to Racket. Create your favorite syntax. image

Exercise 27. Develop the compile-time function dispatch. It translates syntax trees of this shape
(dispatch e
  (s1 e1)
  (s2 e2)
  (default e-def))
into code that evaluates the expression e. If it is not a symbol, e-def is evaluated. If it is a symbol and if this symbol is any of s1 ... s2, the corresponding expression e1 ... e2 is executed. If there is more than one match, the first expression is picked. If there is no match, again e-def is run.

Here is a sample use:
(define (next-state-of-traffic-light current)
  (dispatch current
    [red        'yellow-red]
    [yellow-red 'green]
    [green      'yellow]
    [yellow     'red]
     (if (symbol? current)
          (error "really bad things happened"))]))
Of course, the expression in the clauses do not have to be symbols; they could be proper expressions. image

Exercise 28. Develop a compile-time function that adds

(defun (f:id x:id) e:expr)

to Racket where f becomes the identifier of a function, x its argument, and f the function body. image

Exercise 29. Develop a compile-time function that implements a variant of like if that reacts only to #true and #false in the test position.

Note In a dynamically typed language, it makes some sense to use all values except for #false as equivalents to #true. But some people are offended and this is a first step toward fixing this wart. image