in reply to Re^2: Overcoming addiction to Lisp
in thread Overcoming addiction to Lisp
Whether you can do something with higher order functions or even simpler constructs isn't a great argument against having macros.
Recently I needed to do something for every string of length N or fewer. So I wrote a function that returned a closure that enumerated all strings until exhausting the string space. But I had to loop over the string space a few times in the program, and it got really cumbersome to write things like this:
(flet ((next-string (make-string-enumerator <num>))) (loop for str = (next-string) until (null str) do <body>))
Once I'd written that twice, I realized that I was eventually going to make mistakes writing or rewriting expressions like that, so I wrote a macro that expanded into that expression. Once I had the macro, I could write the following instead of the above:
(dostrings (str <num>) <body>)
Now, maybe you're thinking "That's only a two-line savings in any place where you'd need to do what you're doing", but to me the win is that the macro lets me write only the important things (the <body>, the maximum string length <num>), and the macroexpander takes care of the tedious and error-prone code for me. This isn't just saving typing: I don't have to think up a variable name like next-string whenever I need to loop over all strings, and so I never have to track down bugs introduced by changing variable names when refactoring. If I don't use it outside the macro, I don't even need to remember the purpose or interface for make-string-enumerator, either.
Yeah, I could have written something analogous to the <body> form as a function of the string returned by the enumerator, and written the original loop like this:
(let ((next-string (make-string-enumerator <num>))) (labels ((looper (body enumerator))) (let ((str (funcall enumerator))) (when str (funcall body str) (looper body enumerator)))))
But I'm not sure that's easier to understand than either the original loop form or the dostrings macro, and anyhow it's still long enough that I think I'd want something like my dostrings macro to generate it if I had to write something like that more than once.
Functions (including higher order functions and closures) are one way of factoring code for maintainability; macros are another. They complement each other.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^4: Overcoming addiction to Lisp
by Anonymous Monk on Jun 16, 2005 at 20:01 UTC | |
by runrig (Abbot) on Jun 16, 2005 at 20:20 UTC | |
by Anonymous Monk on Jun 16, 2005 at 20:26 UTC | |
by runrig (Abbot) on Jun 16, 2005 at 20:40 UTC | |
by Anonymous Monk on Jun 16, 2005 at 20:53 UTC | |
by Anonymous Monk on Jul 19, 2005 at 16:46 UTC |