From: Kenneth Tilton on
Bobby Toser wrote:
> hi, i'm learning lisp. :)
>
> i have a lot of code in my game that looks like this:
>
> (defstruct monster name health powers)
>
> (defparameter monster-group
> (list
> (make-monster :name "greg" :health 100)
> (make-monster :name "bobby" :health 200 :powers
> (list :flying))))
>
> i read in this book that you can type less (i want my friends to
> help!) witha macro so i thought that i can do this because it is so
> much easier :)
>
> (defmonster-group monster-group
> ("greg" 100)
> ("bobby" 200 :flying))
>
> but i cant get it to work!
>
> i started with this, but i keep getting really confused at the end.
>
> (defmacro defmonster-group (name &rest rest)
> (let ((monsters (loop for monster in rest collecting monster)))
> `(defparameter ,name
> (list ,@(loop for monster in monsters ????

Try (print (list monster (car monster)))

ie, use your usual debugging tricks to figure out what you have on hand
as data when writing a macro.

btw, depending on the monster-defining language syntax you have in mind,
you can make the above easier with loop's ability to destructure lists:

,@(loop for (name health . powers) in monsters
collect `(make-monster :name ,name
:health ,health
:powers (list ,@powers)))

Note that, yes, the list of powers seen by the macro cannot become the
runtime list in this fashion:

:powers ,powers

.... simply because runtime is not macro-expansion time. Understanding
/that/ will come from experience writing macros and using the debugging
trick above of printing out stuff.

btw, I am not in disagreement with those who think you could just use a
regular function here, but soon enough you will want to write macros and
you'll have the same questions.

>
> can you help me? can i find a good code that shows me how to learn
> this too? im trying practical lisp on the internet but sometimes i
> think i dont get it.

Keep at Practical Common Lisp.

kt


--
http://www.stuckonalgebra.com
"The best Algebra tutorial program I have seen... in a class by itself."
Macworld
From: Captain Obvious on
BT> i read in this book that you can type less (i want my friends to
BT> help!) witha macro so i thought that i can do this because it is so
BT> much easier :)

Yes, but then you might need to look up macro definition to see what's going
on.
It's like compression -- it's more terse, but you need to spend time
"decompressing" it.

So it is good to find good balance...

BT> (defmonster-group monster-group
BT> ("greg" 100)
BT> ("bobby" 200 :flying))

What's about this:

(defparameter *monster-group*
(mapcar #'make-monster-from-list
'(("greg" 100)
("bobby" 200 :flying)))

This doesn't need macro and also you can easily see the structure of what is
going on.
At the same time monster descriptions are as terse as possible, so if you
have many monsters you get nearly optimal representation.

If you have lots of monster groups then maybe macro is a good idea... Or
maybe not.
Anyway, having definition above it is pretty trivial to write a macro:

(defmacro def-monster-group (name list)
`(defparameter ,name
(mapcar #'make-monster-from-list
',list)))

From: Pascal J. Bourguignon on
"Captain Obvious" <udodenko(a)users.sourceforge.net> writes:
> What's about this:
>
> (defparameter *monster-group*
> (mapcar #'make-monster-from-list
> '(("greg" 100)
> ("bobby" 200 :flying)))
>
> This doesn't need macro and also you can easily see the structure of
> what is going on.

But you do not want to see the structure of what is going on! That's
the point of abstraction: to abstract things away!

(defparameter *monster-group*
(monsters '(("greg" 100)
("bobby" 200 :flying))))

It's obvious that monsters is an operator that takes some data and gives
some monsters. You don't need to know anything else.

If you have any doubt, you can always take your scalpel, and in a
bloodbath, have a look at the innards of the poor monsters operator:

(defun monsters (monster-descriptions)
(mapcar (function make-monster-from-description)
monster-descriptions))

--
__Pascal Bourguignon__
http://www.informatimago.com
From: Kenneth Tilton on
Captain Obvious wrote:
> BT> i read in this book that you can type less (i want my friends to
> BT> help!) witha macro so i thought that i can do this because it is so
> BT> much easier :)
>
> Yes, but then you might need to look up macro definition to see what's
> going on.

No different than anything else we do in programming, like creating
functions.

> It's like compression -- it's more terse, but you need to spend time
> "decompressing" it.
>
> So it is good to find good balance...
>
> BT> (defmonster-group monster-group
> BT> ("greg" 100)
> BT> ("bobby" 200 :flying))
>
> What's about this:
>
> (defparameter *monster-group*
> (mapcar #'make-monster-from-list
> '(("greg" 100)
> ("bobby" 200 :flying)))
>
> This doesn't need macro and also you can easily see the structure of
> what is going on.

The whole point of functions or macros is to hide the wiring. The wiring
is just noise in the larger context where one is using any encapsulator.
Furthermore, what happens when one decides to change the wiring? uh-oh.

kt

--
http://www.stuckonalgebra.com
"The best Algebra tutorial program I have seen... in a class by itself."
Macworld
From: Captain Obvious on
??>> What's about this:
??>>
??>> (defparameter *monster-group*
??>> (mapcar #'make-monster-from-list
??>> '(("greg" 100)
??>> ("bobby" 200 :flying)))
??>>
??>> This doesn't need macro and also you can easily see the structure of
??>> what is going on.

PJB> But you do not want to see the structure of what is going on!

It depends. When I'm reading code I'd like to see what's going on. MAPCAR
suggests that monster group is a list, this might be a useful information.

PJB> That's the point of abstraction: to abstract things away!

The point is to choose right level of abstraction. And this depends in many
factors.
Particularly -- are there many groups of monsters? If there are, then
perhaps it is a good idea to introduce abstraction such as monster-group.

PJB> (defparameter *monster-group*
PJB> (monsters '(("greg" 100)
PJB> ("bobby" 200 :flying))))

That's one of ways to do this. def-monster-group abstracts this even
further.

PJB> It's obvious that monsters is an operator that takes some data and
PJB> gives some monsters. You don't need to know anything else.

I might want to know what is monster group. E.g. it is a list in this case,
but it could be an object.