arc> (= a 3)
3
arc> (= b 5)
5
arc> (let a (+ a 4)
(+ a b))
12
arc> (with (a 2 b (+ b 2))
(+ a b))
9
arc> (with (a 6 b 2)
(prn a) (prn b)
(= b a) (= a 'foo)
(prn a) b)
6
2
'foo
6
arc> a
3
arc> b
5
The title of your post is misleading. I think when people saw "How to implement a no-side-effects macro" they read that as "How to implement macros with no side effects" rather than "macro that hides side effects from the surrounding scope".
You asked a simple question about lexical scoping. You got complex and confusing answers about macro hygiene. It is not that Arc has no easy answer to your lexical-scoping question, it is just that your simple question looks like a much harder one about macro hygiene.
Sorry I was unclear - I was indeed actually trying to ask a hard question.
I don't know a priori what variables this code will try to access. I could possibly figure that out with a macro, but some of the details are still unclear to me. I also don't want side effects if annotate, def, mac, or anything like that was run from the no-side-effect'd code.
At any rate, I think just wrapping in a let is insufficient, even if you do know all the variable names. E.g. you can break out of the sandbox with scdr: