Arc Forumnew | comments | leaders | submitlogin
2 points by akkartik 4802 days ago | link | parent

This may be a case where I've painted myself into a corner with wart. Since wart is built atop a lisp-2, I can't just expand the ssyntax a.b to (a b). I have to generate (call a b). Since I want to be able to say things like ++.a, I need call to handle macros as well. But now (call f x) will try to call a macro called f before it looks for the lexical binding.

It's not as big a problem as it may seem. You don't have to worry about future macros shadowing lexical bindings as long as they load afterwards.

The biggest compromise I've had to make because of this: using call-fn (which doesn't expand macros) in accumulate (https://github.com/akkartik/wart/blob/ed9a7d4da1fa017188fce2...) because I wanted to name one of the keyword args unless. So you seem to be watching over your creation after it's left the nest :)

(tangent)

I spent an embarrassingly long time trying to have lexical bindings override macros, before realizing that's impossible in wart: macros get expanded long before lexical bindings are created. So this is a case where you really need a full interpreter; any macro you write can't inspect lexical bindings up the call stack. (oh, for python's nested namespaces..)

(even bigger tangent)

Wart update: arc.arc is just about done. I'm going to start on the webserver, probably not srv.arc but palsecam's http.arc (http://www.arclanguage.org/item?id=11337).

I ended up dividing up ac.scm into 17 files, and arc.arc into 26 (the boundary is fuzzy). So far each file seems highly coherent, and most files are short, so the codebase feels the way the old-timers described forth code: "A component can usually be written in one or two screens of Forth." (http://prdownloads.sourceforge.net/thinking-forth/thinking-f..., pg 41; screens are Forth's units of code.)



3 points by rocketnia 4802 days ago | link

But now (call f x) will try to call a macro called f before it looks for the lexical binding.

Hmm... I'm totally guessing, but this might do the trick:

  -(defmacro call(f &rest args)
  +(defmacro call(f &rest args &environment env)
     (cond
  -    ((macp f)   `(,f ,@args))
  +    ((and (symbolp f) (macro-function f env))   `(,f ,@args))
       ((compose-form-p f)   (expand-composition f args))
       (t  `(call-fn (fslot ,f) ,@args))))
If I'm not mistaken, this looks up f in the lexical environment now, so it should also allow 'call to work with lexically scoped macros.

More information about &environment: http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec...

-----

1 point by akkartik 4802 days ago | link

Great idea, thanks!!

But it doesn't seem to quite work:

  $ sbcl
  * (macro-function 'unless)
  #<FUNCTION (MACRO-FUNCTION UNLESS) {1000ADDAB9}>
  * (macro-function 'foo)
  NIL
  * (let ((unless 34)) (macro-function 'unless))
  #<FUNCTION (MACRO-FUNCTION UNLESS) {1000ADDAB9}>
  * (defmacro macp(x &environment env) (macro-function x env))
  MACP
  * (let ((unless 34)) (macp unless))
  #<FUNCTION (MACRO-FUNCTION UNLESS) {1000ADDAB9}>
  * (let ((unless 34)) (macp foo))
  NIL
Hmm, it's possible it'll only work for dynamically generated macros.. Or am I doing something wrong?

-----

1 point by rocketnia 4802 days ago | link

Remember, you're in a lisp-2. Try this:

  (macrolet ((unless() nil)) (macp unless))  ; should be truthy
  (flet ((unless() nil)) (macp unless))      ; should be falsy
Come to think of it, I don't remember what problem we were trying to solve here. XD Functional position won't use regular local variables anyway....

-----

1 point by akkartik 4801 days ago | link

Lol.

I have a macro called call. Given (call f arg), I would like to return:

if f is a local lambda, (call-fn f arg)

if f is a macro, (f arg)

otherwise, (call-fn f arg)

So yes, it probably isn't possible after all..

-----

1 point by rocketnia 4800 days ago | link

Hmm. Maybe you could shoot for two ssyntaxes, so that it's possible to explicitly override whatever the default rules would do:

  f.arg -> (call f arg)
  f@arg -> (f arg)

-----

1 point by akkartik 4800 days ago | link

Yeah, that may be a good option.

-----

1 point by akkartik 4801 days ago | link

http://blog.jayfields.com/2011/02/clojure-and.html

-----

1 point by evanrmurphy 4802 days ago | link

> I ended up dividing up ac.scm into 17 files, and arc.arc into 26 (the boundary is fuzzy). So far each file seems highly coherent, and most files are short

Ok, I started reading wart. :)

Skimmed that Forth reading. I've only dabbled in Factor, but I'm sometimes tempted to explore concatenative programming more in depth.

-----

1 point by akkartik 4802 days ago | link

Thanks!

Next time somebody says lisp has too many parens I'm going to tell him to put his money where his mouth is and learn forth :)

-----

1 point by akkartik 4801 days ago | link

http://37signals.com/svn/posts/2760-rpn-ever-4-

-----