From: rif
Subject: Re; avoiding eval in macroexpansion
Date: 
Message-ID: <wj0isy7djr1.fsf@five-percent-nation.mit.edu>
> Write a version of the <- macro that evaluates its arguments. It
> should make a good exercise in macro writing (it's not hard). Make
> sure your macro obeys the standard evaluation rules: Each argument
> should be evaluated exactly once, in left to right order.

Thanks for the advice.  Food for thought.  OK, so here's my attempt at
that:

(defmacro <-e (con &optional ant)
  (let ((c (gensym))
        (a (gensym)))
    `(let* ((,c ,con)
            (,a ,ant))
      (length (push (cons (cdr ,c) ,a)
               (gethash (car ,c) *rules*))))))

Of course, with the original <- I could say

(<- (person bob))

But now that of course fails, because person isn't a function.
I instead must say

(<-e '(person bob))

On the positive side, I can now say:

(dolist (p '(donald nancy bumble lina sally))
  (<-e (list 'person p)))

Is there a way to have my cake and eat it too?  Basically, it seems
that what would be useful is a way for a macro to figure out whether
something can possibly be evaluated, and if so, evaluate it, and
otherwise just quote it and use it directly as the original version of
<- did:

(defmacro <- (con &optional ant)
  `(length (push (cons (cdr ',con) ',ant)
            (gethash (car ',con) *rules*))))

Is there any way to do such a thing?  

Cheers and thanks again,

rif

From: rif
Subject: Re: Re; avoiding eval in macroexpansion
Date: 
Message-ID: <wj0el8vdjmr.fsf@five-percent-nation.mit.edu>
Sorry about the changed subject.  I made a gnus booboo.

rif
From: Kalle Olavi Niemitalo
Subject: Re: Re; avoiding eval in macroexpansion
Date: 
Message-ID: <87fztahkn0.fsf@Astalo.y2000.kon.iki.fi>
rif <···@mit.edu> writes:

> (defmacro <-e (con &optional ant)
>   (let ((c (gensym))
>         (a (gensym)))
>     `(let* ((,c ,con)
>             (,a ,ant))
>       (length (push (cons (cdr ,c) ,a)
>                (gethash (car ,c) *rules*))))))

That could as well be a function:

  (defun <-e (con &optional ant)
    (length (push (cons (cdr con) ant)
                  (gethash (car con) *rules*))))

If the function is too slow, try declaring it inline (before
defining it).  Or remove the unnecessary length computation.

> Basically, it seems that what would be useful is a way for a
> macro to figure out whether something can possibly be
> evaluated, and if so, evaluate it, and otherwise just quote it

Well, the macro could check (and (consp con) (fboundp (car con))),
but that would detect neither local functions, nor functions that
will be defined after the macro has already been expanded.

If you really dislike quotes so much, I think you should just
define a separate macro that expands to a call of the first one
with the arguments quoted; then there would not be any ambiguity.
From: rif
Subject: Re: Re; avoiding eval in macroexpansion
Date: 
Message-ID: <wj03cpahb01.fsf@five-percent-nation.mit.edu>
>   (defun <-e (con &optional ant)
>     (length (push (cons (cdr con) ant)
>                   (gethash (car con) *rules*))))
> 
> If the function is too slow, try declaring it inline (before
> defining it).  Or remove the unnecessary length computation.
> 

Yes, I understand.  

> > Basically, it seems that what would be useful is a way for a
> > macro to figure out whether something can possibly be
> > evaluated, and if so, evaluate it, and otherwise just quote it
> 
> Well, the macro could check (and (consp con) (fboundp (car con))),
> but that would detect neither local functions, nor functions that
> will be defined after the macro has already been expanded.
> 
> If you really dislike quotes so much, I think you should just
> define a separate macro that expands to a call of the first one
> with the arguments quoted; then there would not be any ambiguity.

Again, it's not that I actually want to *do* this at all.  This is
just an exercise from Graham's book, that I'm trying to use to get a
better understanding of macros advantages and limitations in a
relatively simple case.

Thanks for all the help.

rif
From: Frode Vatvedt Fjeld
Subject: Re: Re; avoiding eval in macroexpansion
Date: 
Message-ID: <2h4r9qx722.fsf@vserver.cs.uit.no>
rif <···@mit.edu> writes:

> Is there a way to have my cake and eat it too?  Basically, it seems
> that what would be useful is a way for a macro to figure out whether
> something can possibly be evaluated, and if so, evaluate it, and
> otherwise just quote it and use it directly as the original version
> of <- did:

As already stated, there is no obvious reason for this to be a macro
at all. In general, it's better to quote the arguments than to add
extra operators that do automatic quoting, or otherwise deviates from
normal evaluation rules. Magically determining what should be
evaluated and not is almost always a bad idea. It's much more
important that things work as expected than to remove a couple of
characters.  The quote is a single character, and shouldn't be much in
the way, and is more readable since it follows standard evaluation
rules. There are exceptions this, of course. Sometimes the argument
will (nearly) always be quoted. Set and setq is an example where
automatic quoting makes sense (although there are more reasons for
having setq than getting rid of the quote).

-- 
Frode Vatvedt Fjeld