Arc Forumnew | comments | leaders | submitlogin
2 points by aw 5500 days ago | link | parent

Btw, you need an additional quote to get values like your "x" into the eval in all cases... "blub " works because a literal string evaluates to itself, but consider a list like (+ 1 2)

  arc> (let x '(+ 1 2) (repeat 3 (pr x)))
  (+ 1 2)(+ 1 2)(+ 1 2)nil
  arc> (def xrepeat (n . body)
         (eval `(for ,(uniq) 1 ,n ,@body))))
  #<procedure: xrepeat>
  arc> (let x '(+ 1 2) (xrepeat 3 `(pr ,x)))
  333nil
This can be fixed by adding another quote...

  arc> (let x '(+ 1 2) (xrepeat 3 `(pr ',x)))
  (+ 1 2)(+ 1 2)(+ 1 2)nil
Also, you got around the limitation that eval doesn't have access to the lexical variables of its caller by passing in the value of "x", but if you wanted to have your eval/macro to set the value of a variable, that would be harder.

As waterhouse mentioned, two differences between macros and eval are that macros are expanded once when your program is loaded, but eval has to expand and compile its argument every time its called. And like any function eval doesn't have access to the lexical variables of its caller unless you pass in values yourself.

Aside from that, macros and eval are quite similar in the sense that they both treat code as data, and so you have the opportunity to manipulate the code before it gets evaluated.



1 point by ulix 5499 days ago | link

You can get around the problem also in the following "weird" way:

(let x ''(+ 1 2) (xrepeat 3 `(pr ,x)))

but the way you proposed is more "natural" since it respects the "rule" of quoting functions and variables passed at calling time.

Am i wrong if I think that, in the end, the main difference between 'def'+'eval' and 'mac' is that 'mac' allows its code to be evaluated and expanded once, whereas 'def' needs to expand its code every time it is called ?

-----

2 points by rocketnia 5499 days ago | link

Am i wrong if I think that, in the end, the main difference between 'def'+'eval' and 'mac' is that 'mac' allows its code to be evaluated and expanded once, whereas 'def' needs to expand its code every time it is called ?

It's 'eval that expands its code once every time it's called. If you don't use 'eval at all, then all your arc code will be expanded exactly once, at the time you enter it at the REPL or load it from a file (since those are the points where 'eval is called internally).

When you enter the expression (def foo (x) (obj key x)) is at the REPL, it's evaluated as a two-step process: First it's compiled (which expands the (def ...) and (obj ...) macro forms), and then the compiled code is run. When it's run, the body of the function isn't run yet; instead, it's packed up into a procedure and stored as foo. When you call foo later, no expansion takes place, only running of already compiled code.

A better (but not perfect) way to use 'eval equivalently to 'mac is something like this:

  (def mywhen (test . body)
    `(if ,test (do ,@ body))
  
  (eval `(time:for i 1 1000 ,(mywhen '(is i 666) '(prn "Oh no!"))))
If we wanted to make 'do a non-macro, we could do that too:

  (def mydo body
    `((fn () ,@body)))
  
  (def mywhen (test . body)
    `(if ,test ,(apply mydo body)))
  
  (eval `(time:for i 1 1000 ,(mywhen '(is i 666) '(prn "Oh no!"))))
Finally, if we wanted to avoid the use of macros altogether, the example would turn into something like this:

  ; The procedure corresponding to an Arc macro can already be obtained
  ; using 'rep.
  (assign mywhen rep.when)
  (assign mytime rep.time)
  (assign myfor rep.for)
  
  (eval:mytime:myfor 'i '1 '1000 (mywhen '(is i 666) '(prn "Oh no!")))
I could make a few guesses as to why this kind of programming isn't popular in lisps, but my personal reason is that I tend to consider all operators to provide their own syntax, with procedure call syntax just being the default choice. For me, it's inconsistent to have the '(prn ...) syntax be quoted when the (mywhen ...) syntax isn't.

-----

1 point by ulix 5498 days ago | link

Very interesting, thanks!

Do you know where I can find an Arc language reference?

-----

1 point by aw 5498 days ago | link

http://arcfn.com/doc/index.html and http://arcfn.com/2009/06/whats-new-in-arc3.html

-----