I believe the short answer to your questions is that macros and other special forms could be first-class objects--there is no semantic reason to forbid it--but that compiler writers would scream and run away in horror.
(To begin with, any expression of the form ((car x) y ...) could be a macro call, and hence the arguments "y ..." cannot be evaluated until it is determined--at run time--that (car x) is in fact a function. Furthermore, consider this case: (let ((x (cons y z))) ((car h) (cdr x)) (+ 4 (car x))) (car h) could conceivably be a macro that would extract the "x" from the "(cdr x)" expression and produce "(set-car! x 8)" or something like that. Therefore, it would be unsound for the compiler to simply replace "(car x)" with "y". --Calling functions from data structures, as in "((car fs) a b)", seems a rare thing to do, but now we must realize that global variables can usually be modified too, and if ((car mac-list) x) always gets the current car of the mac-list (as opposed to extracting the car once and assuming it'll always remain the same), it would be terribly inconsistent if (f x) did not get the current value of f and, if it happened to be a new macro, to expand some new code and run it. Therefore, the compiler must assume that even "(f (cdr x))" could actually modify the car of x, if f might be redefined in between when this code is compiled and when it is run. I expect real compiler writers could produce more common and compelling examples of important optimizations that become impermissible (or incredibly difficult) in the presence of first-class macros (loop invariants come to mind). I believe it is nevertheless possible--using partial evaluation, rules about when threads learn of updated global variables, and a system of invalidating and recompiling functions--to have efficient compiled code and first-class macros, but I don't think such a system exists right now.) You might find some Scheme or Lisp interpreters that provide macros and special forms as first-class objects--in fact, I have an Arc interpreter that does just this--but don't expect to find it in compilers, or language standards, any time soon. --John Boyle *Science is what we understand well enough to explain to a computer. Art is everything else we do.* --Knuth On Thu, Apr 25, 2013 at 1:43 PM, Stephen Lewis <[email protected]>wrote: > In studying the draft report and the various implementations, I have formed > several questions on which I would like the opinion of an expert. > If this is the wrong place to ask such questions please suggest a more > appropriate forum. > > In the R7RS standard, are macros (i.e syntax objects) considered to be > first-class objects? > [First-class object being an entity that can be constructed at run-time, > passed as a parameter, returned from a subroutine, or assigned to a > variable.] > > For example would these examples be considered to be standard compliant > R7RS > Scheme? The implementations to which I have access do not all behave > in the same way. > > Storing a syntax object in a variable? > > (define myand and) > > Calling my stored object as I can the original? > > (myand #t (+ 1 2 3)) > > Returning a syntax object from a procedure? > > (define (return-op) and) > (define myop (return-op)) > (myop #t (+ 1 2 3)) > > May I call a syntax in the same way I call a primitive procedure? > > (and #t (+ 1 2 3)) > ((return-op) #t (+ 1 2 3)) > ((and and) #t (+ 1 2 3)) > > I have read the R7RS draft and I am having difficulty answering these > questions. > I find that there are "Primitive Expressions" and "Derived Expressions" and > that derived expressions "can instead be defined as macros" but this does > not > seem to be a requirement. The description of a procedure call although in > the Primitive Expression section does not appear to exclude syntax objects. > > "A procedure call is written by enclosing in parentheses an expression > for the procedure to be called followed by espressions for the arguments > to be passed to it." > > An expression that returns a syntax would appear to be allowed. > > (define ops `(,* ,and)) > ((car ops) 2 3) > ((cadr ops) #t #f) > > What about (and and) which is an expression that returns a syntax. > > ((and and) #t (+ 1 2 3)) > > The WG1 charter asserts that "Self consistency is an important objective," > and yet the boolean operators and arithmetic operators do not behave > consistently. In particular as a user of the language it is not obvious > which functions have been implemented as primitives and which as a syntax. > > It appears to be valid to implement the "and" function as a primitive or > as a macro and curiously the boolean "not" function is listed with the > Standard Procedures making it inconsistent with the other boolean > operators. > > There is another situation in which the difference between primitive > procedures and syntax objects makes itself a nuisance and that is in > short-cicuit evaluation of the boolean operators. In the following > expression one might think that the "never" object was not evaluated: > > (and #f never) > > and yet if the "never" object is a syntax it would seem that it is > evaluated. > > (and #f and) > > If these topics have been discussed previously I apologize and please > refer me to the earlier discussion, > > Stephen Lewis > > > _______________________________________________ > Scheme-reports mailing list > [email protected] > http://lists.scheme-reports.org/cgi-bin/mailman/listinfo/scheme-reports >
_______________________________________________ Scheme-reports mailing list [email protected] http://lists.scheme-reports.org/cgi-bin/mailman/listinfo/scheme-reports
