OK, thanks to your last example, it's become clear to me how this works -- but not without a pitfall in usage which I should mention. Consider the following.
Code: Select all
;; Your last definition of 'dolist-index':
(define-macro (dolist-index)
(letex (var ((args) 0 0)
lst ((args) 0 1)
idx ((args) 0 2)
body (cons 'begin (1 (args))))
(set 'idx 0)
(dolist (var lst)
body
(inc 'idx) )
)
)
> (set 'idx 42)
42
> (dolist-index (i '(a b c d e f) idx) (println idx ":" i))
0:a
1:b
2:c
3:d
4:e
5:f
6
> idx
42
;; But now look at this:
> (set 'id 42)
42
> (dolist-index (i '(a b c d e f) id) (println id ":" i))
0:a
1:b
2:c
3:d
4:e
5:f
6
> id
6
Aha! So, we
can trounce a top level 'id' with the use of the 'dolist-index' macro. Hence, we do need a local 'let' scoping for 'idx' (which expands to 'id') in the body of the definition of the 'dolist-index' macro.
Code: Select all
(define-macro (dolist-index)
(letex (var ((args) 0 0)
lst ((args) 0 1)
idx ((args) 0 2)
body (cons 'begin (1 (args))))
(let (idx 0)
(dolist (var lst)
body
(inc 'idx)))))
> (set 'id 42)
42
> (dolist-index (i '(a b c d e f) id) (println id ":" i))
0:a
1:b
2:c
3:d
4:e
5:f
6
> id
42
There, that's better. :-)
So, I guess my confusion before was due to the fact that I was using 'idx' for my index variable reference in the usage. This meant that the 'letex' was binding its symbol 'idx' to the symbol 'idx' passed in by 'args' which happened to be the same symbol -- in my usage they are both 'MAIN:idx'. Hence, 'idx' was being locally bound by the 'letex', essentially, for free.
But when 'idx' is bound to the symbol 'id' instead, we don't get the local 'letex' binding for free (since '(= 'idx 'id)' does not hold -- duh). That's why we needed to add the 'let' in our macro definition.
So, my wrongheaded thought that there was something magical going on with 'letex' beyond expansion and evaluation was due to my poor choice of symbol in my example, combined with just the right amount of muddled thinking. Sorry about that. :-)
(λx. x x) (λx. x x)