Prev: [ANN] Call for Participation for 2010 Workshop on Scheme and Functional Programming
Next: Fascinating interview by Richard Stallman at KTH on emacs historyand internals
From: Kenneth Tilton on 19 Jul 2010 01:50 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 19 Jul 2010 03:11 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 19 Jul 2010 06:56 "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 19 Jul 2010 08:24 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 19 Jul 2010 08:53
??>> 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. |