1. Macros give you laziness. So if you want to conditionally execute part of what's supplied, with functions the user has to supply closures or functions.
(my-if condition then else)
Would execute each of those before a call to my-if, so keeping it a function you'd need:
(my-if condition (lambda () then) (lambda () else))
(bad example, don't make your own if, but illustrates the idea)
2. You want to capture variables from the calling context, same issue as above. Consider the with-resource pattern:
(let ((foo ...))
(with-resource (lambda (r)
(do-something-with-resource r foo)))
Or the macro-d version:
(let ((foo ...))
(with-resource (r)
(do-something-with-resource r foo)))
3. You want to do something that can be done efficiently in Lisp but uses very low level stuffs (like tagbody and go). Rather than writing that (repeatedly if this is a recurring pattern, like for various state machines) you can present a lispier syntax that compiles (via macros) down to the low level primitives (do a macro expand on some of the
do constructs). See [0] for a variation of this idea in Scheme.
4. You want to do something repeatedly and consistently, and want to remove errors. See the definition of defdot in [1]. You could define and register all those functions yourself for each now .<whatever>, or you could let a macro do the heavy lifting.
[0] http://cs.brown.edu/~sk/Publications/Papers/Published/sk-aut... see the linked PDF
[1] http://users.rcn.com/david-moon/MMD/MMD.lisp