Arc Forumnew | comments | leaders | submitlogin
2 points by CatDancer 5625 days ago | link | parent

> Everyone here seems to ignore this eventual issue and focus on the precise problem of 'each, but this was not my point initially.

OK, well, your first example was:

  (if t 1 (amac))
and you complained that the "amac" macro was being expanded at compile time. What if the first argument to 'if isn't known until run time? What if I said

  (if x 1 (amac))
perhaps at run time 'x is going to be false. So we have to expand 'amac, in case that branch of the 'if is invoked.


2 points by palsecam 5625 days ago | link

> So we have to expand 'amac, in case that branch of the 'if is invoked.

But NO!

   cl> (defmacro m () (print "evaluated!"))
   M
   cl> (setf x 2)
   2
   cl> (if x t (m))
   T
   cl> (defun test-m (use-mac?) (if use-mac? (m) nil))
   "evaluated!"     <--- hmmm...
   TEST-M
   cl> (test-m t)
   "evaluated!"
   cl> (test-m nil)
   NIL              <--- ...no it's OK! (no "evaluated!")
Since 'if is a special form we can expect it to do magic. Common Lisp's 'if does, can we agree on that? (I mean seriously. I'm no expert and I don't really know about all this stuff, but I just see some facts. I totally might be wrong).

-----

2 points by CatDancer 5625 days ago | link

Curiosity got the better of me, so I installed Common Lisp.

The (print "evaluated!") itself evaluates to "evaluated!", so here

  cl> (test-m t)
    "evaluated!"
what you're seeing is the value that 'm expands into, not the macro being expanded at that point. If you use something like,

  (defmacro m ()
    (print "evaluated!")
    42)
you'll be able to see what's happening more easily.

-----

1 point by palsecam 5625 days ago | link

Hi hi, nice that you install Common Lisp by curiosity!

However, I don't understand what you want to demonstrate with your macros.

   cl> (defmacro m () (print "evaluated!") 42)
   M
   cl> (if t (m) 43)
   "evaluated"
   42
   cl> (if nil (m) 43)
   43
Ah maybe you mean, when defining the 'test-m function?

   cl> (test-m t)
   42    
Kind of "strange" there is no "evaluated", is this the point? This is a point.

-----

2 points by CatDancer 5625 days ago | link

Yes,

  cl> (test-m t)
  42
is the behavior that I'd expect to see, since the macro was expanded at compile time, when test-m was defined.

The behavior of 'if at the REPL is interesting, perhaps it is to support conditional compilation? However it is a special case, since only at the REPL would we be able to evaluate the test argument to the 'if before compiling the then or else forms. Doing so little as wrapping the 'if statement in a lambda causes the macro to be expanded regardless of the test argument:

  > ((lambda () (if t 3 (m))))
  "evaluated!"
  3

-----

1 point by palsecam 5625 days ago | link

OK here. You're right about the REPL vs normal time eval. The lambda example says everything.

So the 'each of my dreams will be very difficult to have :-D! Maybe with lazy evaluation/JIT compilation [hmmm maybe not needed, see edit below].

Thanks for everything CatDancer!

EDIT:

Lol this stuff has no end. CatDancer I really enjoy all this, but it is late here and I will have to go to bed, seriously!

OK, so no REPL.

In if.lisp:

   (defmacro m () (print "Hello via mac!") 42)

   (defmacro fm ()  ; remember, myeach would also be a macro...
     `(if (eq (read) 'CALLMAC)
        (m) 
        (print "Hello via func")))

   (fm)
On command-line:

   paul@polo-laptop:~ $ echo 'CALLMAC' | sbcl --script if.lisp
   "Hello via mac!" 
   paul@polo-laptop:~ $ echo 'no call' | sbcl --script if.lisp
   "Hello via func"
But yes, if 'fm is a function instead:

   paul@polo-laptop:~ $ echo 'no call' | sbcl --script if.lisp
   "Hello via mac!" 
   "Hello via func"

-----

2 points by CatDancer 5625 days ago | link

Oops, I should have said "top level" not "REPL". My mistake!

"Only at the top level would we be able to evaluate the test argument to the 'if before compiling the then or else forms".

> So the 'each of my dreams will be very difficult to have

Well you know, the Arc compiler knows whether a variable is in the lexical scope. So you could implement your myeach in ac.scm, not using macros, but instead compiling to Scheme.

Or... how about...

  (mac ech args `(each _ ,@args))
:-)

-----

1 point by palsecam 5625 days ago | link

No sorry me because my examples should be better. I use the command line but yes it's still "top level" and this is not enough to test this, right?

But here; OK, if 'fm is a function, the behaviour is "like in Arc". But if it's a macro, it seems to behave "like I want". Or is my example not good? (Sorry I'm really tired here, I can't even realize this :-D).

I mean, don't you think 'myeach as a CL macro would work?

> (mac ech args `(each _ ,@args))

Actually I'm currently using that. I'm just using the name 'each_ instead and define it using the macro currying stuff of twilightsentry (see id=10139, very interesting).

   arc> (= each_ (>_ each '_))
But still you know, one extra character ('_') to type... :-D

-----

2 points by CatDancer 5625 days ago | link

> But if it's a macro, it seems to behave "like I want". Or is my example not good?

Shall I wait until tomorrow to reply so that you can get some sleep? :)

Try

  ((lambda () (fm)))
you can see that only if (fm) is invoked directly from the top level will the macro expansion be avoided.

> I mean, don't you think 'myeach as a CL macro would work?

What you need, in CL or in Arc, is a way to tell if a variable is defined at macro expansion time. Suppose Arc could tell you at macro expansion time if a variable was defined. Then you could say

  (def myeach (first . args)
    (if (defined first)
      `(each _ ,first ,@args)
      `(each ,first ,@args)))
no magic needed in 'if, in either language :)

-----

1 point by palsecam 5625 days ago | link

> Shall I wait until tomorrow to reply so that you can get some sleep? :)

Lol, yes I definitely go to bed now :-)

> ((lambda () (fm))

Nice demonstration indeed.

> What you need, in CL or in Arc, is a way to tell if a variable is defined at macro expansion time.

Right. I may try to modify Arc in this purpose one of these days.

> no magic needed in 'if, in either language :)

Magic definitely sucks :-D!

Thanks a lot CatDancer!

-----

2 points by CatDancer 5625 days ago | link

> can we agree on that?

No, because I don't know what CL is doing.

-----

1 point by palsecam 5625 days ago | link

Well, if I dive deeply into CL one of these days, I'll tell you :-), but this not in my plans for the near future :-/

You are right to refuse "magic".

For Arc, oh this is way too much difficult for me, but if I had to try to solve the problem, I think I'd try to add a level of abstraction between the Scheme runtime and the Arc one (?!) Macros currently, as you know, directly run in the Scheme environment (am I all right?). I'd try to avoid that, and have more control over them by "compiling" them to a special form (`ar-macall') but not directly execute them (?!) And so 'if could then have a "higher priority" than macro expansion (?!)

But these are pure ideas in the wild. I am not able even to try, so don't listen this crap :-D

-----

2 points by CatDancer 5625 days ago | link

> try to solve the problem

which problem, the 'myeach problem or the 'if problem?

-----

1 point by palsecam 5625 days ago | link

Hi hi, this thread is definitely too big now :-D

The 'if/macroexpansion problem.

-----