using labels in macros
Posted: Sat Jul 25, 2009 9:51 am
Hey,
I've recently started to learn lisp, and to exercise what I've learnt I've started writing a simple connect 4 game. I want to write a macro to check if a number of positions are on the board. Using inspiration from the sbcl source code for the AND macro as a example of writing macros which work on an unlimited number of parameters using &rest, I first wrote this:
But then I saw that the (>= ,(first positions) 0) and the (< ,(first positions) +board-size) tests were being repeated, so I tried to group those tests together using labels:
The problem with that is that I've got ` marks nested in a , mark, nested in a ` mark, which I've read is a bad idea (and I can see why: it could easily get confusing). Also, the macro is recursive, and I'm going to get a copy of my labels code for every recursion, which seems very foolish. Is there an easier way to use functions defined with LABELS in macros? I could just write and extra test function, but I'd rather know how to do this without cluttering up the namespace.
By the way, I originally tried to start writing this as a function, but I couldn't work out how to send (rest positions) through to the recursive call, it would just complain that was was being sent through for the recursion was 'not of type REAL'. If this can be more easily written as a function, then I'd like to hear how. (Although even if in this case I'm better off with a function, I'd still like to know how to mix LABELS with macros in cases like this, just for educational purposes.)
Thanks!
I've recently started to learn lisp, and to exercise what I've learnt I've started writing a simple connect 4 game. I want to write a macro to check if a number of positions are on the board. Using inspiration from the sbcl source code for the AND macro as a example of writing macros which work on an unlimited number of parameters using &rest, I first wrote this:
Code: Select all
(defmacro on-board-p (&rest positions)
(cond ((endp positions) t)
((endp (rest positions))
`(and (>= ,(first positions) 0)
(< ,(first positions) +board-size)))
(t
`(and (>= ,(first positions) 0)
(< ,(first positions) +board-size)
(on-board-p ,@(rest positions))))))
Code: Select all
(defmacro on-board-p (&rest positions)
`(labels ((test (p)
(and (>= p 0)
(< p +board-size))))
,(cond ((endp positions) t)
((endp (rest positions)) `(test ,(first positions)))
(t
`(and (test ,(first positions))
(on-board-p ,@(rest positions)))))))
By the way, I originally tried to start writing this as a function, but I couldn't work out how to send (rest positions) through to the recursive call, it would just complain that was was being sent through for the recursion was 'not of type REAL'. If this can be more easily written as a function, then I'd like to hear how. (Although even if in this case I'm better off with a function, I'd still like to know how to mix LABELS with macros in cases like this, just for educational purposes.)
Thanks!