Yes, exactly. I see why that is true. But think about a parallel function:
(def n (f a)
(f a))
In the function, you can pass f as an argument to call. In a macro, f is passed implicitly in the environment the macro is expanded in. The method of passing f to the macro m seems very much like using dynamic scoping to pass arguments to functions. My question is, what about a macro system where you could pass real arguments to macros? I.e., other macros (or functions, etc.)? What makes these things different?
> what about a macro system where you could pass real arguments to macros?
Like this
(mac n (f a)
`(,f ,a))
(n [+ _ 1] 9)
==> 10
where you pass a form that is then evaluated by the macro, or did you mean something else? Macros' arguments aren't evaluated, so you can pass only forms. To pass the result of a computation in CL (not in Arc) you can use read macros, that are evaluated before macro expansion time:
(n #.(computation) 9)
This is quite unusual, because macros are intended mainly to modify the syntax, so it's quite natural to make them work on the syntax itself (i.e. the forms).
Ah, I see this. I think I have been thinking of macros differently than you have (and probably wrongly). I suppose lexical scoping for macros would make the most difference in the case where a macro expands to a function call, like this:
(let x 0 ; call (count) to keep a count of things
(def count () (set x (+ x 1))))
; count-ops: count how many lines of code you run.
(mac count-ops body
(if body
(cons (car body)
(cons '(count)
(count-ops (cdr body))))
'())
(def foo ()
(count-ops ; this count-ops call fails
(with (count 1 step 2)
; do some loopy stuff here
)))
If that's not a compelling example, pretend that count-ops is inserting an interrupt check between every two lines of code. Why is dynamic scoping better for cases like these?
As for real arguments to macros, yes, I meant something like the CL stuff. You're right, though, that macros modify syntax, and I wasn't thinking about them that way. Two posts up you said that macros are "expanded in place". I think that you were thinking about the effect macros have on the code they're called on, whereas I was thinking about the call to the actual macro procedure, and passing arguments to it.