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: Bobby Toser on 18 Jul 2010 11:30 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 ???? 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. thanks!! bobby
From: D Herring on 18 Jul 2010 12:08 On 07/18/2010 11:30 AM, Bobby Toser wrote: .... > (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! .... A couple points: * Use plain functions when possible. Macros are only needed for processing arguments without evaluating them, introducing variables, etc. * Decompose your problem into smaller parts. Here, your defmonster-group does two or three separate things. It creates a parameter, and it populates it with a list of monsters using a custom syntax. In this case, a bottom-up construction seems natural. Here's a solution for the last of those tasks. (defun monster-builder (name health &rest powers) (make-monster :name name :health health :powers powers)) Then we build on that (defmacro monster-list (&rest monsters) (cons 'list (loop for monster in monsters collecting (apply 'monster-builder monster)))) And finally get what you asked for (defmacro defmonster-group (name &rest monsters) `(defparameter ,name (monster-list ,@monsters))) and a simple test example. (defmonster-group *test* ("greg" 100) ("bobby" 200 :flying)) *test* -> (#S(MONSTER :NAME "greg" :HEALTH 100 :POWERS NIL) #S(MONSTER :NAME "bobby" :HEALTH 200 :POWERS (:FLYING))) - Daniel
From: joswig on 18 Jul 2010 12:19 On 18 Jul., 17:30, Bobby Toser <bobbyto...(a)hotmail.com> 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 ???? > > 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. If you want to create a list of monsters from some data, write a function for that. There is not much use of a macro for that. > > thanks!! > > bobby
From: Pascal J. Bourguignon on 18 Jul 2010 14:38 Bobby Toser <bobbytoser(a)hotmail.com> writes: > 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 If you want to avoid a couple of days of debugging sometime in a not too far away future, do name your special variables with stars! (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 ???? > > 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. Macros are functions. So if you can write a function, you can write a macro. And of course, if you cannot write a macro, it's because you cannot write a function. So start by concentrating on writing functions. Namely, given a list such as: (("greg" 100) ("bobby" 200 :flying)) there is nothing preventing you to write a function that would build a list such as: (#<monster :name "greg" :health 100 :power ()> #<monster :name "bobby" :health 200 :power (:flying)>) Hint: you could use MAPCAR Therefore you could write: (defparameter *monster-group* (monsters '(("greg" 100) ("bobby" 200 :flying)))) without a need for any macro. -- __Pascal Bourguignon__ http://www.informatimago.com/
From: Joshua Taylor on 18 Jul 2010 18:29
On 2010.07.18 12:08 PM, D Herring wrote: > Here's a solution for the last of those tasks. > (defun monster-builder (name health &rest powers) > (make-monster :name name > :health health > :powers powers)) This part can already be done with the defstruct. (defstruct (monster (:constructor monster-builder (name health &rest powers)) (:constructor make-monster)) ; for default constructor name health powers) => MONSTER (make-monster :name "name" :health 34 :powers (list 'fire 'water)) => #S(MONSTER :NAME "name" :HEALTH 34 :POWERS (FIRE WATER)) (monster-builder "other-name" 38 (list 'water 'earth)) => #S(MONSTER :NAME "other-name" :HEALTH 38 :POWERS ((WATER EARTH))) //JT |