Problem 8: and and or again, But hygienic (optional, 0pts)

You must have known the power of cs61a scheme macro. However, this define-macro syntax special form is not a part of standard scheme today. Your editor (with default settings) may not be able to highlight this identifier.

To figure out the reason, let's take a closer look on the real programming language scheme. Scheme is designed and developed by Guy L. Steele and Gerald Jay Sussman. In 1978, they released The Revised Report on SCHEME: A Dialect of LISP.

After that, The Revised Report on SCHEME became the standard specification of scheme. The nᵗʰ edition of this document is called The Revisedⁿ Report on the Algorithmic Language Scheme (rnrs). The newest one is r7rs. You can download them all at Scheme Reports

The mainly feature introduced by r5rs (1998) is the hygienic macro. The other form of macro is then deprecated.

Why do we need hygienic macro? Let's consider my/and macro from problem 4. Now we have this code:

(my/and (1 t))

this will be expanded to:

(let ((t 1))
  (if t
      t
      #f))

and then eval to 1. However,

(and 1 t)

will throw an error. So our implementation (my/and) will not be equivalence to and. This is called the hygiene problem. It's a difficult problem.

We mainly have two solutions:

  • use (gen-sym) to generate symbols.
  • completely change the macro system to avoid this problem.

(standard) Scheme use the second one. To define a macro and in (standard) scheme, you have to write code like this:

(define-syntax and
  (syntax-rules ()
    ((_) #t)
    ((_ e) e)
    ((_ e1 e2 e3 ...)
     (let ((t e1)) 
       (if t (and e2 e3 ...) #f)))))

Note we use t here again, but the macro expander will not use this symbol:

> (expand '(and t 1))
(let ([#{t l660ym05an8kdp7ojf0qoql86-0} t])
  (if #{t l660ym05an8kdp7ojf0qoql86-0} 1 #f))

In this problem, let's image if we have gen-sym in cs61a scheme (in fact, we don't have it, we even can't implement it).

Use gen-sym to define a hygienic version of my/and and my/or.

; only used for testing if your code could expand to a valid expression 
(define (gen-sym) 'sdaf-123jasf/a123)

; in these two functions you can use gen-sym function.
; assumption:
; 1. scm> (eq? (gen-sym) (gen-sym))
;    #f
; 2. all symbol generate by (gen-sym) will not in the source code before macro expansion
(define-macro (my/and/2 operands)
  'YOUR-CODE-HERE
)

(define-macro (my/or/2 operands)
  'YOUR-CODE-HERE
)

This two macro will be tested for if they could expand to a valid expression.