Monday, May 03, 2004

Lisp Macros Rock

Lisp macros are the one feature that distinguish it from almost all other programming languages on the planet. For the benefit of people who would not understand, I shall make an attempt to explain them. Consider a programming language as a tool for feeding a set of instructions to a computer. This can be interpreted or compiled and then called. The call (usually functions) will try to either just perform something or return values after some processing.

Lets take addition on a calculator. So you press 1, +, 2, = and expect it to read out the result 3. The + is a good example of what a function could be. In this instance, it expects two arguments, which are numbers. The two arguments are your variables, which, we shall name x and y. So the value of x or y can be anything as long as it is a number. Anytime you enter x + y, The function + performs its operations and returns the result. Most programming languages work the same way in the most basic sense. So there is a translation layer between the expression and the machine which tells the machine what it is reading. So

Expression -> Interpreter -> Result

Compilers just add another layer to this, often reducing the time of the last phase.

Now imagine you can change what the interpreter or compiler sees at runtime. These are called macros.

Expression -> Macro Translation -> Interpreter -> Result

Lisp macros are like Lisp functions that generate Lisp code and then evaluate them as well. Where is this useful is what most people ask. Well, for one, creating your own language on top of Lisp especially domain related. I am currently writing a persistent database query system in Lisp and one of the macros that was really needed was something that can parse a string, say "var1", extract its symbol value, var1, create a global variable by that name var1 and assign some value to it.

The macro looked somewhat like this


(defmacro set-var-from-string (str val)
(let ((var (gensym)))
`(let ((,var (coerce (read-from-string ,str) 'symbol)))
(setf (symbol-value ,var) ,val))))


I can call this as follows

(set-var-from-string "var1" "test")


Which will create a variable var1 and store the value "test" in it. I could also call it from a variable

(setf x "var2")


and then call

(set-var-from-string x "test2")


This call wil create a variable var2 and store the value "test2" in it. I encourage you to try to write an equivalent of this macro in any other non-lisp like language.



0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home