I've written a macro which wraps make-instance so that I can create an
arbitrary class in a package -
(defmacro new (class &body args)
(eval `(append '(make-instance ',class) ',args)))
This is just a cosmetic thing, as the package in which it appears
isn't aimed at users with huge experience of Lisp. I understand that
eval is something to avoid in most circumstances, but I can't see any
other way to write this. Any thoughts/suggestions?
You don't need to call EVAL like that. Just calling append will do:
(append `(make-instance ',class) args)
you can even try it quickly in the repl, without defining a macro:
(let ((class 'myclass) (args '(yadda-yadda-yadda)))
(append `(make-instance ',class) args))
=> (MAKE-INSTANCE (QUOTE MYCLASS) YADDA-YADDA-YADDA)
or, of course, using macroexpand-1 after having defined the macro:
(macroexpand-1 '(new myclass yadda-yadda-yadda))
=> (MAKE-INSTANCE (QUOTE MYCLASS) YADDA-YADDA-YADDA)
Now, Common Lisp provides a quickier way to do this than calling
append: the ,@ operator, which behaves like , but gets rid of an
additional level of parentheses (i.e. `(1 ,@'(2 3 4) 5) produces the
list (1 2 3 4 5)).
So here's the shorter new:
(defmacro new (class &rest args)
`(make-instance ',class ,@args))
cheers
Alessio Stalla
On Feb 22, 8:04 pm, Alessio <·············@gmail.com> wrote:
> You don't need to call EVAL like that. Just calling append will do:
>
> (append `(make-instance ',class) args)
>
> you can even try it quickly in the repl, without defining a macro:
>
> (let ((class 'myclass) (args '(yadda-yadda-yadda)))
> (append `(make-instance ',class) args))
>
> => (MAKE-INSTANCE (QUOTE MYCLASS) YADDA-YADDA-YADDA)
>
> or, of course, using macroexpand-1 after having defined the macro:
>
> (macroexpand-1 '(new myclass yadda-yadda-yadda))
>
> => (MAKE-INSTANCE (QUOTE MYCLASS) YADDA-YADDA-YADDA)
>
> Now, Common Lisp provides a quickier way to do this than calling
> append: the ,@ operator, which behaves like , but gets rid of an
> additional level of parentheses (i.e. `(1 ,@'(2 3 4) 5) produces the
> list (1 2 3 4 5)).
>
> So here's the shorter new:
>
> (defmacro new (class &rest args)
> `(make-instance ',class ,@args))
>
> cheers
> Alessio Stalla
Well thanks guys for all the expert advice! Quite obviously I am
trying to run before I can walk... :) The ,@ operator I had no idea
about, it achieves PRECISELY the result I was after.
On Fri, 22 Feb 2008, Cortez wrote:
> On Feb 22, 8:04 pm, Alessio <·············@gmail.com> wrote:
> > You don't need to call EVAL like that. Just calling append will do:
> >
> > (append `(make-instance ',class) args)
> >
> > you can even try it quickly in the repl, without defining a macro:
> >
> > (let ((class 'myclass) (args '(yadda-yadda-yadda)))
> > (append `(make-instance ',class) args))
> >
> > => (MAKE-INSTANCE (QUOTE MYCLASS) YADDA-YADDA-YADDA)
> >
> > or, of course, using macroexpand-1 after having defined the macro:
> >
> > (macroexpand-1 '(new myclass yadda-yadda-yadda))
> >
> > => (MAKE-INSTANCE (QUOTE MYCLASS) YADDA-YADDA-YADDA)
> >
> > Now, Common Lisp provides a quickier way to do this than calling
> > append: the ,@ operator, which behaves like , but gets rid of an
> > additional level of parentheses (i.e. `(1 ,@'(2 3 4) 5) produces the
> > list (1 2 3 4 5)).
> >
> > So here's the shorter new:
> >
> > (defmacro new (class &rest args)
> > `(make-instance ',class ,@args))
> >
> > cheers
> > Alessio Stalla
>
> Well thanks guys for all the expert advice! Quite obviously I am
> trying to run before I can walk... :) The ,@ operator I had no idea
> about, it achieves PRECISELY the result I was after.
>
The important advice given here was not to use eval.
Using eval the way you did here simply gives the wrong
result. (Well, maybe not, but its about 99.993% likely
that you didn't really want the behaviour of your first
macro):
(defmacro new1 (class &rest args)
`(make-instance ',class ,@args))
(defmacro new2 (class &rest args)
(eval `(make-instance ',class ,@args))
1.
(let ((sum 90))
(new1 bank sum))
...works
2.
(let ((sum 90))
(new2 bank sum))
...gives error about undefined variable 'sum'.
On Fri, 22 Feb 2008, Kjetil S. Matheussen wrote:
>
> The important advice given here was not to use eval.
> Using eval the way you did here simply gives the wrong
> result. (Well, maybe not, but its about 99.993% likely
> that you didn't really want the behaviour of your first
> macro):
Rainer Joswig:
>
> I think it EVALuates the APPEND function. The
> code
Dang. Thanks Rainer, I didn't see that. Sorry, the
original macro was behaving correct, although the
implementation was a bit unconventional. :-)
Den Fri, 22 Feb 2008 11:11:54 -0800 skrev Cortez:
> I've written a macro which wraps make-instance so that I can create an
> arbitrary class in a package -
>
> (defmacro new (class &body args)
> (eval `(append '(make-instance ',class) ',args)))
>
> This is just a cosmetic thing, as the package in which it appears isn't
> aimed at users with huge experience of Lisp. I understand that eval is
> something to avoid in most circumstances, but I can't see any other way
> to write this. Any thoughts/suggestions?
How about
(defmacro new (class &body args)
(append '(make-instance) (list (list 'quote class)) args))
? Or, to be more idiomatic (and readable):
(defmacro new (class &body args)
`(make-instance ',class ,@args))
Your problem comes from trying to use backquote AND manual list
construction at the same time. It's either-or, they serve the same
purpose, so if you do both, you'll have to evaluate the results twice,
hence the need for extra EVAL.
Cheers,
Maciej
Maciej Katafiasz wrote:
> (defmacro new (class &body args)
> `(make-instance ',class ,@args))
I consider it an api mistake and misconception to define "new" as a
macro. There is nothing about new that is not functional, and
mistakenly defining functions as macros blocks proper operator
combinations that are important in reasonable languages like CL.
new should be defined as a function to avoid surprising programmers who
might use it inside other programming tools. Just like it is in Java.
(No one can fugure out what new does in C++ :-) If there is some
compile-time optimization or customization that you would like done for
calls to new then you should write a compiler macro.
> I consider it an api mistake and misconception to define "new" as a
> macro. There is nothing about new that is not functional, and
> mistakenly defining functions as macros blocks proper operator
> combinations that are important in reasonable languages like CL.
Well in this case, I think the purpose of the new macro is to make the
quotation of the class argument unnecessary. So for its purpose
(presenting a more familiar syntax to newbies) it has its sense. Of
course defining new like that loses a lot of possibilities you had
with make-instance (use it as a first-class object, pass it a class
obtained by find-class, etc.) - but the newbies using new wouldn't
have exploited those possibilities anyway...
> new should be defined as a function to avoid surprising programmers who
> might use it inside other programming tools. Just like it is in Java.
Huh? Is new a function in Java? Didn't know that... but for sure, even
if it is, I seriously doubt it would behave like regular Java methods
- you won't be able to override it, for example.
In the OP's case, defining new as a function would have been simply
"renaming" make-instance. (Or better, making it accessible through the
symbol new).
> (No one can fugure out what new does in C++ :-) If there is some
> compile-time optimization or customization that you would like done for
> calls to new then you should write a compiler macro.
On Feb 23, 8:52 am, Alessio <·············@gmail.com> wrote:
> > I consider it an api mistake and misconception to define "new" as a
> > macro. There is nothing about new that is not functional, and
> > mistakenly defining functions as macros blocks proper operator
> > combinations that are important in reasonable languages like CL.
>
> Well in this case, I think the purpose of the new macro is to make the
> quotation of the class argument unnecessary. So for its purpose
> (presenting a more familiar syntax to newbies) it has its sense. Of
> course defining new like that loses a lot of possibilities you had
> with make-instance (use it as a first-class object, pass it a class
> obtained by find-class, etc.) - but the newbies using new wouldn't
> have exploited those possibilities anyway...
Yes - well, almost right. It was really designed as a way of hiding
make-instance completely, not just the quote. And the typical user is
not so much a newbie as someone unlikely ever to delve deeper into
Lisp. It forms part of a library of functions and classes for music
analysis, and requires its own domain-specific (and somewhat
simplified) syntax.
>
> > new should be defined as a function to avoid surprising programmers who
> > might use it inside other programming tools. Just like it is in Java.
>
> Huh? Is new a function in Java? Didn't know that... but for sure, even
> if it is, I seriously doubt it would behave like regular Java methods
> - you won't be able to override it, for example.
> In the OP's case, defining new as a function would have been simply
> "renaming" make-instance. (Or better, making it accessible through the
> symbol new).
>
> > (No one can fugure out what new does in C++ :-) If there is some
> > compile-time optimization or customization that you would like done for
> > calls to new then you should write a compiler macro.
In article
<····································@p43g2000hsc.googlegroups.com>,
Cortez <············@hotmail.co.uk> wrote:
> I've written a macro which wraps make-instance so that I can create an
> arbitrary class in a package -
MAKE-INSTANCE does not create classes. It creates instances.
What do packages have to do with it?
What does make you think that you can't create arbitrary classes 'in
a package'? What does that mean?
>
> (defmacro new (class &body args)
Not &body. Use &rest.
> (eval `(append '(make-instance ',class) ',args)))
Can you explain what above should do? It looks totally confused.
This does the same:
(defmacro new (class &rest args)
`(make-instance ',class ,@args))
(new foo) is the same as (make-instance 'foo) .
But why do you need that? Your explanation makes no sense to me.
>
> This is just a cosmetic thing, as the package in which it appears
> isn't aimed at users with huge experience of Lisp. I understand that
> eval is something to avoid in most circumstances, but I can't see any
> other way to write this. Any thoughts/suggestions?
I'd say you might what to step back a little and read a Lisp/CLOS
tutorial. Your code and your question shows that you
haven't understand some basics. It is not a good idea
then to try to use CLOS and Macros, especially not combined.
On Feb 22, 7:43 pm, Rainer Joswig <······@lisp.de> wrote:
> In article
> <····································@p43g2000hsc.googlegroups.com>,
>
> Cortez <············@hotmail.co.uk> wrote:
> > I've written a macro which wraps make-instance so that I can create an
> > arbitrary class in a package -
>
> MAKE-INSTANCE does not create classes. It creates instances.
>
> What do packages have to do with it?
>
> What does make you think that you can't create arbitrary classes 'in
> a package'? What does that mean?
Sorry, should have been clearer - this is just a cosmetic shorthand
for make-instance, nothing more. Yes, instances not classes - that's
what I meant, apologies. The classes are already defined in the
package.
>
>
>
> > (defmacro new (class &body args)
>
> Not &body. Use &rest.
>
> > (eval `(append '(make-instance ',class) ',args)))
>
> Can you explain what above should do? It looks totally confused.
>
> This does the same:
>
> (defmacro new (class &rest args)
> `(make-instance ',class ,@args))
>
Thanks, I was completely ignorant of ,@. It achieves what I wanted.
> (new foo) is the same as (make-instance 'foo) .
> But why do you need that? Your explanation makes no sense to me.
As I said, it's purely cosmetic. It's part of a domain-specific
library (music analysis) not aimed at advanced Lispers.
>
>
>
> > This is just a cosmetic thing, as the package in which it appears
> > isn't aimed at users with huge experience of Lisp. I understand that
> > eval is something to avoid in most circumstances, but I can't see any
> > other way to write this. Any thoughts/suggestions?
>
> I'd say you might what to step back a little and read a Lisp/CLOS
> tutorial. Your code and your question shows that you
> haven't understand some basics. It is not a good idea
> then to try to use CLOS and Macros, especially not combined.
In article
<····································@b29g2000hsa.googlegroups.com>,
Cortez <············@hotmail.co.uk> wrote:
> On Feb 22, 7:43 pm, Rainer Joswig <······@lisp.de> wrote:
> > In article
> > <····································@p43g2000hsc.googlegroups.com>,
> >
> > Cortez <············@hotmail.co.uk> wrote:
> > > I've written a macro which wraps make-instance so that I can create an
> > > arbitrary class in a package -
> >
> > MAKE-INSTANCE does not create classes. It creates instances.
> >
> > What do packages have to do with it?
> >
> > What does make you think that you can't create arbitrary classes 'in
> > a package'? What does that mean?
>
> Sorry, should have been clearer - this is just a cosmetic shorthand
> for make-instance, nothing more. Yes, instances not classes - that's
> what I meant, apologies. The classes are already defined in the
> package.
>
> >
> >
> >
> > > (defmacro new (class &body args)
> >
> > Not &body. Use &rest.
> >
> > > (eval `(append '(make-instance ',class) ',args)))
> >
> > Can you explain what above should do? It looks totally confused.
> >
> > This does the same:
> >
> > (defmacro new (class &rest args)
> > `(make-instance ',class ,@args))
> >
>
> Thanks, I was completely ignorant of ,@. It achieves what I wanted.
Even without backquoute you would not need EVAL.
(defmacro new (class &rest args)
(append (list 'make-instance (list 'quote class))
args))
>
> > (new foo) is the same as (make-instance 'foo) .
> > But why do you need that? Your explanation makes no sense to me.
>
> As I said, it's purely cosmetic. It's part of a domain-specific
> library (music analysis) not aimed at advanced Lispers.
>
> >
> >
> >
> > > This is just a cosmetic thing, as the package in which it appears
> > > isn't aimed at users with huge experience of Lisp. I understand that
> > > eval is something to avoid in most circumstances, but I can't see any
> > > other way to write this. Any thoughts/suggestions?
> >
> > I'd say you might what to step back a little and read a Lisp/CLOS
> > tutorial. Your code and your question shows that you
> > haven't understand some basics. It is not a good idea
> > then to try to use CLOS and Macros, especially not combined.
Rainer Joswig wrote:
> (defmacro new (class &rest args)
> `(make-instance ',class ,@args))
>
> (new foo) is the same as (make-instance 'foo) .
> But why do you need that?
You never created a macro just to hide the quote? :) Seems like
overkill, but I do it all the time. That little tick always seems like
exposed wiring.
kenny
--
http://smuglispweeny.blogspot.com/
http://www.theoryyalgebra.com/
"In the morning, hear the Way;
in the evening, die content!"
-- Confucius
On Fri, 22 Feb 2008, Cortez wrote:
> I've written a macro which wraps make-instance so that I can create an
> arbitrary class in a package -
>
> (defmacro new (class &body args)
> (eval `(append '(make-instance ',class) ',args)))
>
> This is just a cosmetic thing, as the package in which it appears
> isn't aimed at users with huge experience of Lisp. I understand that
> eval is something to avoid in most circumstances, but I can't see any
> other way to write this.
Don't think of eval as something to avoid in most circumstances.
eval is a really cool thing which should be used as often as necesarry.
But in this case, though, its not necesarry.
In article <·································@notam02.uio.no>,
"Kjetil S. Matheussen" <··············@notam02.no> wrote:
> On Fri, 22 Feb 2008, Cortez wrote:
>
> > I've written a macro which wraps make-instance so that I can create an
> > arbitrary class in a package -
> >
> > (defmacro new (class &body args)
> > (eval `(append '(make-instance ',class) ',args)))
> >
> > This is just a cosmetic thing, as the package in which it appears
> > isn't aimed at users with huge experience of Lisp. I understand that
> > eval is something to avoid in most circumstances, but I can't see any
> > other way to write this.
>
> Don't think of eval as something to avoid in most circumstances.
> eval is a really cool thing which should be used as often as necesarry.
> But in this case, though, its not necesarry.
It's worse than not necessary, it's WRONG. It will make the instance at
compile time, not execution time.
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
On Feb 23, 1:38 am, Barry Margolin <······@alum.mit.edu> wrote:
> In article <·································@notam02.uio.no>,
> "Kjetil S. Matheussen" <··············@notam02.no> wrote:
>
>
>
> > On Fri, 22 Feb 2008, Cortez wrote:
>
> > > I've written a macro which wraps make-instance so that I can create an
> > > arbitrary class in a package -
>
> > > (defmacro new (class &body args)
> > > (eval `(append '(make-instance ',class) ',args)))
>
> > > This is just a cosmetic thing, as the package in which it appears
> > > isn't aimed at users with huge experience of Lisp. I understand that
> > > eval is something to avoid in most circumstances, but I can't see any
> > > other way to write this.
>
> > Don't think of eval as something to avoid in most circumstances.
> > eval is a really cool thing which should be used as often as necesarry.
> > But in this case, though, its not necesarry.
>
> It's worse than not necessary, it's WRONG. It will make the instance at
> compile time, not execution time.
>
> --
> Barry Margolin, ······@alum.mit.edu
> Arlington, MA
> *** PLEASE post questions in newsgroups, not directly to me ***
> *** PLEASE don't copy me on replies, I'll read them in the group ***
Thanks again guys for all the helpful comments. I've learnt a lot just
from this one question. After all, you DO learn by your mistakes
(well, hopefully!).
In article <····························@comcast.dca.giganews.com>,
Barry Margolin <······@alum.mit.edu> wrote:
> In article <·································@notam02.uio.no>,
> "Kjetil S. Matheussen" <··············@notam02.no> wrote:
>
> > On Fri, 22 Feb 2008, Cortez wrote:
> >
> > > I've written a macro which wraps make-instance so that I can create an
> > > arbitrary class in a package -
> > >
> > > (defmacro new (class &body args)
> > > (eval `(append '(make-instance ',class) ',args)))
> > >
> > > This is just a cosmetic thing, as the package in which it appears
> > > isn't aimed at users with huge experience of Lisp. I understand that
> > > eval is something to avoid in most circumstances, but I can't see any
> > > other way to write this.
> >
> > Don't think of eval as something to avoid in most circumstances.
> > eval is a really cool thing which should be used as often as necesarry.
> > But in this case, though, its not necesarry.
>
> It's worse than not necessary, it's WRONG. It will make the instance at
> compile time, not execution time.
I think it EVALuates the APPEND function. The
code
(EVAL `(APPEND '(MAKE-INSTANCE ...
is the same as
(APPEND '(MAKE-INSTANCE ...
KSM> Don't think of eval as something to avoid in most circumstances.
EVAL should be used only to evaluate code that was not known in load/compile
time.
it should be avoided in all other circumstances, except, maybe, some very
weird cases.
KSM> But in this case, though, its not necesarry.
often people who are learning Lisp use EVAL when they have problems
understanding macros, closures, or backquotes (as in this case). so, it's a
good indicator.
On Sat, 23 Feb 2008, Alex Mizrahi wrote:
> KSM> Don't think of eval as something to avoid in most circumstances.
>
> EVAL should be used only to evaluate code that was not known in load/compile
> time.
> it should be avoided in all other circumstances, except, maybe, some very
> weird cases.
>
Right, but you cut out "eval is a really cool thing which should be used
as often as necesarry." And I doubt we disagree very much about when to
use eval and when not to. However, why impose such a rule as the
one you gave above? Are you 100% sure that eval should be used only
to evaluate code not known in load/compile time except for some very
weird cases? Theres no mathematic proof for that statement to be
correct, and other programmers might, theoretically, prefer to do
things differently.
> KSM> But in this case, though, its not necesarry.
>
> often people who are learning Lisp use EVAL when they have problems
> understanding macros, closures, or backquotes (as in this case). so, it's a
> good indicator.
>
Well, its better to use eval than to give up. :-)
??>> EVAL should be used only to evaluate code that was not known in
??>> load/compile time. it should be avoided in all other circumstances,
??>> except, maybe, some very weird cases.
??>>
KSM> Right, but you cut out "eval is a really cool thing which should be
KSM> used as often as necesarry." And I doubt we disagree very much about
KSM> when to use eval and when not to. However, why impose such a rule as
KSM> the one you gave above? Are you 100% sure that eval should be used
KSM> only to evaluate code not known in load/compile time except for some
KSM> very weird cases? Theres no mathematic proof for that statement to be
KSM> correct,
there is no 100% correct proof, but it can be shown that if we have
something available before we actually run program, it's possible to embed
this into the code (via macros etc), and get benefits of compile-time
opitmizations, checks etc.
if we'll do this in run-time via EVAL, we'll get slowdown and more chances
to get errors.
rare cases when people have some code, but prefer to delay loading it until
it's really needed are typically better handled via LOAD or coercing lambda
expression to a function.
KSM> and other programmers might, theoretically, prefer to do things
differently.
all inhabitants of Venus *might* have blue skin, theoretically. maybe they
also prefer to use EVAL.
while this could be true, it's not interesting (and not scientific) to
consider such cases.
it would be much more interesting if you can tell about cases when EVAL is
good to use. probably i'll learn something new this way..
On Feb 23, 7:37 pm, "Alex Mizrahi" <········@users.sourceforge.net>
wrote:
> KSM> Don't think of eval as something to avoid in most circumstances.
>
> EVAL should be used only to evaluate code that was not known in load/compile
> time.
> it should be avoided in all other circumstances, except, maybe, some very
> weird cases.
>
> KSM> But in this case, though, its not necesarry.
>
> often people who are learning Lisp use EVAL when they have problems
> understanding macros, closures, or backquotes (as in this case). so, it's a
> good indicator.
The reason I used EVAL and APPEND was because I didn't know about
the ,@ operator. I had actually come across it, but couldn't find
anything in the Hyperspec about it (it's not listed under non-
alphabetic characters).
In article
<····································@t66g2000hsf.googlegroups.com>,
Cortez <············@hotmail.co.uk> wrote:
> On Feb 23, 7:37 pm, "Alex Mizrahi" <········@users.sourceforge.net>
> wrote:
> > KSM> Don't think of eval as something to avoid in most circumstances.
> >
> > EVAL should be used only to evaluate code that was not known in load/compile
> > time.
> > it should be avoided in all other circumstances, except, maybe, some very
> > weird cases.
> >
> > KSM> But in this case, though, its not necesarry.
> >
> > often people who are learning Lisp use EVAL when they have problems
> > understanding macros, closures, or backquotes (as in this case). so, it's a
> > good indicator.
>
> The reason I used EVAL and APPEND was because I didn't know about
> the ,@ operator. I had actually come across it, but couldn't find
> anything in the Hyperspec about it (it's not listed under non-
> alphabetic characters).
That explains why you used APPEND, but why did you use EVAL?
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
On Feb 24, 11:26 pm, Barry Margolin <······@alum.mit.edu> wrote:
> In article
> <····································@t66g2000hsf.googlegroups.com>,
>
>
>
> Cortez <············@hotmail.co.uk> wrote:
> > On Feb 23, 7:37 pm, "Alex Mizrahi" <········@users.sourceforge.net>
> > wrote:
> > > KSM> Don't think of eval as something to avoid in most circumstances.
>
> > > EVAL should be used only to evaluate code that was not known in load/compile
> > > time.
> > > it should be avoided in all other circumstances, except, maybe, some very
> > > weird cases.
>
> > > KSM> But in this case, though, its not necesarry.
>
> > > often people who are learning Lisp use EVAL when they have problems
> > > understanding macros, closures, or backquotes (as in this case). so, it's a
> > > good indicator.
>
> > The reason I used EVAL and APPEND was because I didn't know about
> > the ,@ operator. I had actually come across it, but couldn't find
> > anything in the Hyperspec about it (it's not listed under non-
> > alphabetic characters).
>
> That explains why you used APPEND, but why did you use EVAL?
>
> --
> Barry Margolin, ······@alum.mit.edu
> Arlington, MA
> *** PLEASE post questions in newsgroups, not directly to me ***
> *** PLEASE don't copy me on replies, I'll read them in the group ***
Because without it (new some-class) just yields (MAKE-INSTANCE 'SOME-
CLASS). So I EVALed it.
Den Sun, 24 Feb 2008 23:03:01 -0800 skrev Cortez:
>> > The reason I used EVAL and APPEND was because I didn't know about the
>> > ,@ operator. I had actually come across it, but couldn't find
>> > anything in the Hyperspec about it (it's not listed under non-
>> > alphabetic characters).
>>
>> That explains why you used APPEND, but why did you use EVAL?
>>
> Because without it (new some-class) just yields (MAKE-INSTANCE 'SOME-
> CLASS). So I EVALed it.
This is completely backwards and shows you have no understanding what
macros and/or backquote do. Incidentally, this is exactly why EVAL is
considered harmful -- not because it doesn't have legitimate uses, but
because if you think yours is legitimate, you're almost certainly wrong.
And that doesn't hold just for newbies, see
http://xach.livejournal.com/131456.html for a good cautionary tale.
Bottom line -- the next time you find yourself trying something in a
basic case and failing, do *not* use EVAL. Instead, spend your time on
making sure you understand what the thing actually does. I'm especially
worried about you writing some sugar layer for "newbs" when you're a
complete newb (at least as far as macros go) yourself. That never results
in solid code.
Cheers,
Maciej
In article
<····································@q33g2000hsh.googlegroups.com>,
Cortez <············@hotmail.co.uk> wrote:
> On Feb 24, 11:26 pm, Barry Margolin <······@alum.mit.edu> wrote:
> > In article
> > <····································@t66g2000hsf.googlegroups.com>,
> >
> >
> >
> > Cortez <············@hotmail.co.uk> wrote:
> > > On Feb 23, 7:37 pm, "Alex Mizrahi" <········@users.sourceforge.net>
> > > wrote:
> > > > KSM> Don't think of eval as something to avoid in most circumstances.
> >
> > > > EVAL should be used only to evaluate code that was not known in load/compile
> > > > time.
> > > > it should be avoided in all other circumstances, except, maybe, some very
> > > > weird cases.
> >
> > > > KSM> But in this case, though, its not necesarry.
> >
> > > > often people who are learning Lisp use EVAL when they have problems
> > > > understanding macros, closures, or backquotes (as in this case). so, it's a
> > > > good indicator.
> >
> > > The reason I used EVAL and APPEND was because I didn't know about
> > > the ,@ operator. I had actually come across it, but couldn't find
> > > anything in the Hyperspec about it (it's not listed under non-
> > > alphabetic characters).
> >
> > That explains why you used APPEND, but why did you use EVAL?
> >
> > --
> > Barry Margolin, ······@alum.mit.edu
> > Arlington, MA
> > *** PLEASE post questions in newsgroups, not directly to me ***
> > *** PLEASE don't copy me on replies, I'll read them in the group ***
>
> Because without it (new some-class) just yields (MAKE-INSTANCE 'SOME-
> CLASS). So I EVALed it.
But that does not makes sense.
I try to explain it:
A macro is a function that gets code and creates code.
It would usually NOT need to call eval.
Input code, example:
(new foo :bar 10)
Output code for above example:
(make-instance 'foo :bar 10)
How can you develop a macro that does that?
The resulting macro using list building constructs is:
(defmacro new (class &rest args)
(list* 'make-instance (list 'quote class) args))
We can test that:
CL-USER 2 > (macroexpand '(new foo :bar 10))
(MAKE-INSTANCE (QUOTE FOO) :BAR 10)
So it works.
What was your problem? You added quoting where it was not necessary.
CL-USER 3 > (append '(1 2) '(3 4))
(1 2 3 4)
Append is a normal function.
You were putting a (back) quote in front of it:
CL-USER 4 > '(append '(1 2) '(3 4))
(APPEND (QUOTE (1 2)) (QUOTE (3 4)))
Then you were removing the quote by adding an EVAL:
CL-USER 5 > (eval `(append '(1 2) '(3 4)))
(1 2 3 4)
If you really like EVAL you can do that multiple times:
CL-USER 7 > (eval (eval (eval (eval (eval `````(append '(1 2) '(3 4)))))))
(1 2 3 4)
But why not just write:
CL-USER 8 > (append '(1 2) '(3 4))
(1 2 3 4)
So, your EVAL was totally useless. It was there just because there
was a unnecessary quoting level.
Now since you seem to really like EVAL let's add it to the macro from above:
(defmacro new (class &rest args)
(eval `(list* 'make-instance (quote ',class) ',args)))
Now you have a macro, that creates a form that gets evaluated and then creates
another form.
CL-USER 29 > (macroexpand '(new foo :bar 10))
(MAKE-INSTANCE (QUOTE FOO) :BAR 10)
We have now added a completely useless EVAL. Just like in your code.
If you really really really really really like EVAL, why not do this:
(defmacro new (class &rest args)
(eval (eval (eval (eval (eval `''''(list* 'make-instance (quote ',class) ',args)))))))
We have now added five completely useless EVAL.
Now you have a macro, that creates a form that gets evaluated and then creates
another form that gets evaluated and then creates another form..........
Compare the macro from above:
(defmacro new (class &rest args)
(list* 'make-instance (list 'quote class) args))
Now you have a macro, that creates a form. No EVAL.
Remember in Lisp you should write:
CL-USER 73 > (+ 1 2)
3
and not
CL-USER 74 > (eval '(+ 1 2))
3
and not
CL-USER 75 > (eval '(eval '(+ 1 2)))
3
and not
CL-USER 76 > (eval '(eval '(eval '(+ 1 2))))
3
and not
CL-USER 77 > (eval (eval '(eval '(eval '(+ 1 2)))))
3
and not
CL-USER 78 > (eval '(eval (eval '(eval '(eval '(+ 1 2))))))
3
..............................................................
--
http://lispm.dyndns.org/
Cortez <············@hotmail.co.uk> writes:
> I've written a macro which wraps make-instance so that I can create an
> arbitrary class in a package -
>
> (defmacro new (class &body args)
> (eval `(append '(make-instance ',class) ',args)))
I won't count how many ways this macro is wrong.
> This is just a cosmetic thing, as the package in which it appears
> isn't aimed at users with huge experience of Lisp. I understand that
> eval is something to avoid in most circumstances, but I can't see any
> other way to write this. Any thoughts/suggestions?
Instead of writting (new my-class :attr1 literal1 :attr2 literal2)
you could write:
(apply (function make-instance) 'my-class
'(:attr1 literal1 :attr2 literal2))
Or more simply:
(make-instance 'my-class :attr1 'literal1 :attr2 'literal2)
This would give you even more functionality:
(let ((some-class (compute-some-class))
(some-args (compute-some-args)))
(apply (function make-instance) some-class some-args))
or:
(make-instance (compute-some-class)
:attr1 (compute-some-value 1) :attr2 (compute-some-value 2))
--
__Pascal Bourguignon__ http://www.informatimago.com/
ATTENTION: Despite any other listing of product contents found
herein, the consumer is advised that, in actuality, this product
consists of 99.9999999999% empty space.