Side effects Andre van Tonder (13 Jul 2006 15:10 UTC)
Re: Side effects dyb@xxxxxx (29 Jul 2006 21:17 UTC)

Side effects Andre van Tonder 13 Jul 2006 15:10 UTC

The SRFI does not currently specify how side effects during expansion are
treated.  This was not relevant for syntax-rules, but does make a difference
in a procedural macro system.

I am particularly interested in cases where a common strategy may involve
repeating the same expansion step, or only partially expanding an expression,
typically to determine if it is a definition.

In the following example:

   (define-syntax foo
     (let ((count 0))
       (lambda (s)
         (set! count (+ 1 count))
         count)))

   (define-syntax bar
     (let ((count 0))
      (lambda (s)
       (set! count (+ count 1))
       (syntax-case s ()
        ((_ x) (with-syntax ((count count))
                 (syntax (list count (foo) x)))))))

   (let ()
     (define x (foo))
     (bar x))

the result could be any of:

  - (1 1 2)

    If the first non-definition (bar x) in the let is expanded atomically
    as soon as it is encountered.

  - (1 2 1)

    If the first non-definition (bar x) is expanded only far enough to
    determine if it is a definition before expanding the RHS of the
    define.

  - (2 2 1)

    If we do as in the previous case, but do not save the partially
    expanded (bar x), instead re-expanding it from the beginning
    after the definitions are all expanded (I have seen implementations
    that do this).

This seems academic, but I do think the differences could conceivably lead to
difficulties in macros that rely on side effects to register compile-time
information, as in record or object systems.  For example, if BAR were
a record definition, I would probably feel most comfortable if I could rely on
the expression being epanded atomically (the first behaviour above).

Regards
Andre