I read the link you listed and the problem that you ran into. I've only had about a day's worth of Clojure programming and year or two of Common Lisp but I'm fairly certain that I wouldn't have fallen into your particular trap. Reason being that a quick glance at the docs would have told me that doto was a macro and what it did.
Of course you know that. Your argument is that in a purely functional language, all you need to know is the function call subtree where you are. The same block of code always evaluates the same way regardless of context. Which is neat.
However, your example begs the question: If you didn't know what doto did, why where you tying to modify what it was being passed? You clearly didn't know what any of the subforms did either; otherwise you would have noticed that the methods appeared to be called on objects that didn't have them. So yes, in Lisps, and in side-effecty languages, you can't treat code as algebra and refactor it without knowing whether the operators in your code are macros or functions, and what, in general, they do.
Except, then again, sometimes you can. In your case, you definitely could have. If you wrote your macro to generate exactly the code you were trying to refactor, you wouldn't have hit this problem. If you're changing the logic of the code, you need to be aware of how it's logic works, but if you are just factoring out bits of code with macros, you just need to be faithful to the original, in which case, it doesn't matter whether the macro is in another macro or contains global values. It should simply produce the same code and execute the same.
Of course you know that. Your argument is that in a purely functional language, all you need to know is the function call subtree where you are. The same block of code always evaluates the same way regardless of context. Which is neat.
However, your example begs the question: If you didn't know what doto did, why where you tying to modify what it was being passed? You clearly didn't know what any of the subforms did either; otherwise you would have noticed that the methods appeared to be called on objects that didn't have them. So yes, in Lisps, and in side-effecty languages, you can't treat code as algebra and refactor it without knowing whether the operators in your code are macros or functions, and what, in general, they do.
Except, then again, sometimes you can. In your case, you definitely could have. If you wrote your macro to generate exactly the code you were trying to refactor, you wouldn't have hit this problem. If you're changing the logic of the code, you need to be aware of how it's logic works, but if you are just factoring out bits of code with macros, you just need to be faithful to the original, in which case, it doesn't matter whether the macro is in another macro or contains global values. It should simply produce the same code and execute the same.