| When I think of macros, I'm generally thinking about getting a syntax tree at runtime and doing transformations on it. The closest thing related to this in a mainstream language is LINQ in .NET. When passing a lambda expression, you can either get a method reference that you can execute, or you can get a syntax tree of that expression. It is effectively used in Linq to Sql to query databases using the same syntax you would use for querying in-memory collections of objects. You can also teach it to do pretty sweat things, like doing data transformations using the GPU. Check out this project for instance: http://brahma.ananthonline.net/ Also, macros are not necessarily executed at compile-time as in C/C++ - in Lisp a macro has no boundaries to when or how it gets executed. A macro is just a piece of code that can call normal functions and that returns a piece of code that will then get executed. One common use-case is for achieving lazy evaluation in a language that isn't lazy and so most macros are trivial to understand. But you can have other use-cases, like in the above example with Linq, where the piece of code getting generated depends on runtime conditions. I do agree that macros can make code harder to understand, but then again, I've seen horribly over-engineered, poorly implemented and unreadable pieces of Java code and so I think it all comes down to having a culture for code readability than about having a language that forces you to do things in a certain way. |