I used to have the same issue understanding the benefit. One simple example that helped it clicked for me was considering the `when` or `unless` macro.
They're just very simple macros based around the `if` special form. Because they're macros, they can just treat the body as data, i.e. it's not executed as part of argument resolution.
If you wanted to make a `when` function in Python, the "body" would have to be a callable like a lambda or named function.
I know this probably isn't the most compelling use case but I found it to be a really simple way to understand some of the benefits of macros and how they could be used elsewhere.
So let's say i have a lisp macro along the lines of
(analyze 1 2 expensiveComputation)
In python, to prevent evaluating all arguments when running analyze, I'd have to pass expensiveComputation as a callable or a function partial and remember to call it if I need it.
Whereas in lisp, I can pass whatever expensive variable I want into the macro because it will only get evaluated when using (expensiveComputation ...) and that's baked into the language.
They're just very simple macros based around the `if` special form. Because they're macros, they can just treat the body as data, i.e. it's not executed as part of argument resolution.
If you wanted to make a `when` function in Python, the "body" would have to be a callable like a lambda or named function.
I know this probably isn't the most compelling use case but I found it to be a really simple way to understand some of the benefits of macros and how they could be used elsewhere.