From: Bill Atkins Date: 2005-09-28T01:40:44+09:00 Subject: Re: Fwd: Lisp macros +1 As Paul Graham points out, the point of macros is syntactic abstraction. If you find yourself writing similar code over and over or find that you're using a pattern over and over, you write out a macro and abstract away that similarity. This makes code easier to understand and increases maintainability by reducing multiple instances of the same concept into a single macro. The difference is analagous to that between procedural and object-oriented programming. It is difficult to explain to a procedural programmer why objects are so useful ("But what use are classes? I can just use different functions and name them appropriately."). The case is the same with macros; they are a different way of thinking, and provide additional power that non-Lisp languages do not offer. Ruby's blocks can get you a lot of what Lisp macros can, but they are not a complete substitute. For instance, the dotimes macro Robbie demonstrated is possible in Ruby: The dotimes macro could be implemented (and is implemented) as 10.times do |i| .. end The two bits of code are functionally identical, but it's clear that the Ruby version is jumping through more hoops than the macro version to present a counting abstraction to the user (dotimes (i 10) ....) The Ruby version must contort itself to work with Ruby's block syntax, while the macro version has no such restrictions to deal with. I am not digging on Ruby, but just trying to point out why macros are different. The dotimes macro can choose when and how its parameters are evaluated. So i is not treated as a variable name simply because dotimes does not want to treat it that way. The code passed as "..." is not run directly, but is instead run in the way dotimes wants it to (that is, it is executed 10 times). Hopefully, someone can supply some really cool examples. I haven't done enough Lisp to have any, but http://www.gigamonkeys.com/book is a good place to start reading about cool macros. Bill On 9/27/05, Robbie Carlton wrote: > code as data is what makes lisp macros so powerful. > > In a c macro you have the power of a little macro language to manipulate > strings, in a lisp macro you have the power of lisp language to manipulate > lisp data structures. I'll elaborate. > > When the compiler sees a call to a macro it passes all of the arguments to > the macro, before evaluating. > so in a call like > > (dotimes (i 10) > (do-some-crazy-thing) > (print i)) > > the macro dotimes is passed the list (i 10) and the list > ((do-some-crazy-thing) (print i)) > the macro can then operate on them as data, using the full power of lisp. At > the end of all this, the macro returns another piece of data, a list, which > is then interpreted as a lisp form, code, and evaluated. > > If lisp code wasn't the same as lisp data, macros would be a lot less > powerful as you would have to have two languages, one for manipulating lisp > data, and another for manipulating lisp code (this is what you get in c). > > Hope this helps. Sorry the example isn't very enlightening, it's difficult > to illustrate the power of macros in (< 500 words) as they're very > complicated. If you'd like to know more* ... learn lisp :) > > Now I will stop with the lisp advocacy. > > *on lisp by Paul Graham is the bible on macros, but it's a little hard for > someone who's new to lisp, try practical common lisp by Peter Siebel, (both > are available free online). > > On 9/27/05, Devin Mullins wrote: > > > > Devin Mullins wrote: > > > > > The big thing Lisp has that Ruby can't do is code-as-data. I wish I > > > could provide a good example of how that might be used practically, > > > but it's been quite a while since I touched lisp. > > > > > > Devin > > > > Well, nobody's provided an example. The best I can do is provide more > > explanation. Since code is just (blah blah (blah blah)) -- that is, just > > a list -- and Lisp has the capability to delay evaluation (I think with > > an '), you can pass code into another function and have that function > > actually manipulate the internals of your code, and build some new code > > out of it. You could, maybe, write something that stripped all the print > > statements out at runtime... Crappy example... > > > > Help! Is there a Lisper in the house? > > > > Devin > > > > > > > > -- Bill Atkins