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

Side effects

This page is part of the web mail archives of SRFI 93 from before July 7th, 2015. The new archives for SRFI 93 contain all messages, not just those from before July 7th, 2015.

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