Use a practical macro decision framework: prefer functions, choose macros for syntax or evaluation control, and review the generated code before sharing the abstraction.
Macros are worth considering only when a function cannot express the call shape. A function receives evaluated arguments. A macro receives code forms and can decide when, whether, or where those forms appear in generated code.
| Question | Prefer |
|---|---|
| Can a function, higher-order function, or data map express this clearly? | Do not write a macro. |
| Do you need to delay, skip, or repeat evaluation? | A macro may be justified. |
| Do you need to introduce a binding or control-flow shape at the call site? | A macro may be justified. |
| Would callers have to read the expansion to trust it? | Keep the macro small or do not ship it. |
For Java engineers, treat a macro like generated source inside the language. The call site can be elegant, but the expansion is the code your team must own.