Twenty years ago when I was trying to explain macros to fellow Java programmers I would say, "what if Java didn't have try/catch/finally, could you add it?" I guess in some theoretical way you could, but the answer is not really.
Then I would show them how to use a simple macro I had written for sql statements that would turn a block of statements into a transaction:
(sql-tran
(statements)
(commit)
(rollback))
I would point out that only the commit or rollback expressions would execute. It also generated symbols so that these could be nested.
At the end of the day, you get code that looks like:
(transfer-money amount from-account to-account)
and it really feels like cheating because it's all wrapped up in transactions and handles errors without having to see that splattered across the code.
Even as a beginner in Lisp I had more and easier code reuse than I've had in any language before or since.
Then I would show them how to use a simple macro I had written for sql statements that would turn a block of statements into a transaction: (sql-tran (statements) (commit) (rollback))
I would point out that only the commit or rollback expressions would execute. It also generated symbols so that these could be nested.
At the end of the day, you get code that looks like:
(transfer-money amount from-account to-account)
and it really feels like cheating because it's all wrapped up in transactions and handles errors without having to see that splattered across the code.
Even as a beginner in Lisp I had more and easier code reuse than I've had in any language before or since.