Macros are lisp functions that take code in and spit code out. It's easy to understand this concept, but it's not always easy to see the myriad benefits such a feature has. I know people will argue that you can do this in other languages, but those people are dead wrong - my intent here is to explain what a macro is, rather than to present a substantial macro that nobody but Scheme or lisp programmers would understand.
Macros are used to create new special operators in Lisp that behave just like built in ones like if, loop, let, etc. -- it's a given that without learning macros you can't understand the truly groovy examples, but here's a simple one: Say I only have if/then/else, and I want to make a simpler form called "when" that only ever has a then clause.
"if" is written thusly:
(if test then-clause else-clause) ... a.k.a. predicate, consequent, alternative
I want "when"to look like this:
(when test then-clauses...)
please excuse the lack of proper lisp indentation.
I can define a macro that is run whenever a function is compiled which uses "when," right along with any other macros I want, in this manner:
(defmacro when (test &body body)
`(if,test (progn,@body) nil))
This allows me to use the "when" macro around any conditional code I like, wherever I like, and it will be treated as if I had the if statement right there in the code -- it's not like a function call because the "arguments" passed to a macro are CODE, not VALUES (well, except in lisp they're the same thing, but that's another posting).
For the "can't write games in it" crowd...
Say I want macros to push and pop transformation matrices in a 3d game. It's basically not reasonable to do this in C++ any other way than by hand because if you pass functions into a function which does the pushing and popping they lose their lexical environment and end up having to be more complicated than just doing it by hand. Not so with macros.
Macros are used to create new special operators in Lisp that behave just like built in ones like if, loop, let, etc. -- it's a given that without learning macros you can't understand the truly groovy examples, but here's a simple one: Say I only have if/then/else, and I want to make a simpler form called "when" that only ever has a then clause.
"if" is written thusly:
... a.k.a. predicate, consequent, alternative
(if test then-clause else-clause)
I want "when"to look like this: ...)
(when test then-clauses
please excuse the lack of proper lisp indentation.
I can define a macro that is run whenever a function is compiled which uses "when," right along with any other macros I want, in this manner:
(defmacro when (test &body body) ,test (progn ,@body) nil))
`(if
This allows me to use the "when" macro around any conditional code I like, wherever I like, and it will be treated as if I had the if statement right there in the code -- it's not like a function call because the "arguments" passed to a macro are CODE, not VALUES (well, except in lisp they're the same thing, but that's another posting).
For the "can't write games in it" crowd...
Say I want macros to push and pop transformation matrices in a 3d game. It's basically not reasonable to do this in C++ any other way than by hand because if you pass functions into a function which does the pushing and popping they lose their lexical environment and end up having to be more complicated than just doing it by hand. Not so with macros.