[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Side effects

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))

  (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

 - (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).