Explanation of macros; Haskell macros

Pascal Costanza costanza at web.de
Mon Nov 3 13:39:54 EST 2003


Joachim Durchholz wrote:

>> This becomes especially useful as soon as your protocols become more 
>> sophisticated, and you need to insert instructions at arbitrary places 
>> in the code being passed to a macro, or need to control evaluation of 
>> the code being passed in some other details.
> 
> Inserting "at arbitrary places" seems rather unmodular to me.
> Either the macro would have to know about the code that it's being used 
> in, so that it can identify the places where to insert the code.
> Or the code using the macro will have to pass information to the macro - 
> which, in a HOF context, means that the code using the HOF approach will 
> have to pass the code for "before the insertion point" and "after the 
> insertion point" as separate parameters, and the HOF would do the 
> necessary linkage between the two codes.
> I'm not sure that macros offer a significant gain here.

a) "insert instructions at arbitrary places in the code being passed to 
a macro" means that the macro modifies the code that is being passed to 
it - not the code that surrounds the use site of a macro.

b) For macros, you don't have to partition the information the macro 
needs to do its job into several parameters. A macro just analyzes the 
code that is being passed to it, and automagically does the right thing. 
;) (This is part of the reason why macros allow you to build 
abstractions that don't leak: you don't have to arrange the parameters 
for the macro according to the implementation details of the macro, but 
in more or less completely arbitrary ways.)

c) The significant gain of macros is this: Macros rewrite syntax trees, 
and you can implement any language feature, domain-specific or not, via 
syntax tree rewriting. This means that, no matter what happens during 
software development, you can always find a way to express things in a 
convenient way.

This is mainly a psychological effect: macros greatly reduce the need to 
plan ahead and allow for experimenting with program designs: Just write 
down the code as you imagine to be suitable for the concrete problem at 
hand, and then start to implement it from there. It's very likely that 
you will find out how to implement the machinery beneath in that process 
and then write a bunch of macros that translate your original ideas on 
top of that machinery. You don't have to plan ahead what the "right" 
design is for you problem.

Switch from FP to OOP later on? No problem: rewrite the machinery, 
reimplement your macros, don't change the high-level code. Oops, your 
field should have been methods, or externally stored in a database? No 
problem: rewrite the machinery, reimplement your macros, don't change 
the high-level code.

Without macros, it's very likely that in these cases, when you have to 
change the design of your libraries, you also have to change client 
code. With macros, you don't have to. At least not in 99% of the cases. ;-P

>> Because of this high level of expressive power that macros provide, 
>> Common Lispers use them regularly even for simple things. You can 
>> effectively write domain-specific abstractions that don't leak, and 
>> therefore it is justified to use them even for simple protocols.
> 
> OK, but the same can be said for HOFs.
> The question is: in what ways are macros superior to HOFs to accomplish 
> this?

Most importantly: HOFs as such are rarely domain-specific. So whenever 
your library requires you to express a piece of code with an anonymous 
function, you give away details about the implementation of a specific 
feature.

> See it this way: Macros are a way to create blocks of code. HOFs that 
> return functions do the same: they take a few functions (and possibly 
> some value arguments), stick them together, and return the result. If 
> the HOF is evaluated at compile time (something that I'd expect if both 
> functions and values submitted to the HOF are constant), then you too 
> have a mechanism that creates a block of code.

I don't care about blocks of code or compile-time evaluation, at least 
not most of the time. When I see this...


(with-open-file (stream filename
                  :direction :output
                  :if-does-not-exist :create)
   (format stream "some output"))


...I see a piece of code that tells the machine to open a file in a 
specified way, write some output to it and then closes it gracefully. I 
don't care whether this is achieved by means of OOP abstraction, HOFs, 
or whatever. Such code "talks" only about the necessary details and 
nothing else.

>>> Does anybody have a keyword-style list of useful applications of the 
>>> macro facilities?
>>
>>
>> Do you have a keyword-style list of useful applications of functions?
> 
> 
> I think you forgot a smiley - at least, that question is entirely silly. 
> If you have a real point to make, please make it explicit; I have too 
> little time to devote to decoding your intents. (And if you don't want 
> to spend time on trivialities, then please understand that I don't, too.)

Your question is as silly as mine. ;)

If you want to get an idea what you can do with macros, Paul Graham 
provides an excellent overview in his book "On Lisp" that you can 
download for free at http://www.paulgraham.com/onlisp.html


Pascal





More information about the Python-list mailing list