Arc Forumnew | comments | leaders | submitlogin
1 point by nlavine 6155 days ago | link | parent

Hmm. Well, just glancing at the arc1 source code, we have these three lines in ac.scm:

  (define (ac-call fn args env)
    (let ((macfn (ac-macro? fn)))
      (cond (macfn
         ....)))
which could be replaced by

  (define (ac-call fn args env)
    (let ((macfn (and (not (memq fn env)) (ac-macro? fn))))
      (cond (macfn
         ......))),
preventing the cars of applications being automatically macroexpanded. I don't understand the other problem you brought up. Why would (fn (macroname ...) ...) not work?


3 points by almkglor 6155 days ago | link

Actually, that was the point I was planning to do the hack: (let ...) and friends deduce down to (fn ...) forms, so logically the place to do replacement of variable names should be in (fn ...) forms. ac-call is involved in function calling, which is really related.

However I've since changed my mind, because the problem then becomes:

  (withs (do 1 re 2 mi 3)
    (+ do re mi))
Bonus points if you figure out why your solution will also fail the above ^^

-----

3 points by nlavine 6154 days ago | link

It fails because the outermost let form in the expansion redefines do, and the innermost let body uses do. Nice : )

I think, however, that I have made an exciting discovery: we have a hygienic macro system! Or at least half of one!

Here's the current implementation of withs:

  (mac withs (parms . body)
    (if (no parms) 
        `(do ,@body)
        `(let ,(car parms) ,(cadr parms) 
           (withs ,(cddr parms) ,@body))))
And here's an alternate implementation:

  (mac withs (parms . body)
    (if (no parms)
        (apply (rep do) body)
        (apply (rep let) (car parms) (cadr parms)
          `(withs ,(cddr parms) ,@body)))))
Because we know that macros are really just tagged procedures, we can apply them ourselves and let lexical scoping guarantee that they aren't shadowed!

Granted, it's ugly, and it only solves part of the problem, but I think it's a reasonable place to start hacking from.

-----

1 point by almkglor 6154 days ago | link

>Granted, it's ugly, and it only solves part of the problem, but I think it's a reasonable place to start hacking from.

Oh, no. Because it means you'll need to (apply (rep macro) body) whenever you need to use a macro within a different macro. That's just too much bug-prone work and is completely unreasonable.

-----

1 point by nlavine 6153 days ago | link

Yeah.

Also, on further reflection, I think perhaps the original hack is better - even given the weird behavior of (withs (do 1 re 2 mi 3) ...). If we're really making a language for quick hacking and prototyping, and giving the programmer all the tools they need, then maybe letting them redefine do is exactly the right thing to do. In your example it doesn't make sense, sure, but what if it was redefined as a function? Or a new macro that did something interesting with its body (inserted debug statements)? Maybe we should deliberately let the programmer redefine everything they want (as pg says) - and make sure not to write anything in a safer, more idiot-proof style. That's not the point of arc.

(Namespace collision is another issue. But we need a way to deal with that that only affects things when you want it to, and never when you don't.)

-----

3 points by almkglor 6153 days ago | link

Oh no, heck no squared. Because if you do, that means that every macro has to publish any symbols-in-functional-position it actually creates. And every programmer has to check every macro he or she uses to make sure that any local variables he or she has do not conflict with the symbols-in-functional-position published by the macros. Hades breaking loose and all that. Funny action at a distance.

As for redefining a macro - then let's implement 'macrolet, that way we don't have capture.

-----