The conflict might happen only if you pass "free variable" around; that is the case with
but not with
As long as one does not pass free variables around he is safe. The problem most frequently occurs with Newlisp macros (actually, fexprs). These rely on free variables. If one defines
ifnt, inverse of
if with
Code: Select all
(define-macro (ifnt condition else then)
(if (eval condition)
(eval then)
(eval else)))
then all variables used in, for example,
Code: Select all
(ifnt (< a b) (setf a 4)(setf b 4))
are passed to
ifnt as free variables. In that case the problem is exactly the same as in Common Lisp macros, where the solution is in use of gensyms. Newlisp doesn't have gensym, but one can easily define his own.
Code: Select all
(define (gensym)
(inc gensym-counter)
(sym (append "G-" (string gensym-counter))))
However, in almost all cases, use of
gensym is overkill. I defined two functions for myself:
set-protected1 and
set-protected2.
Code: Select all
(set-protected1 'ifnt (lambda(c e t)(if (eval c)(eval t)(eval e)))
'(e c t))
will actually produce code lambda-expression like
Code: Select all
(lambda([ifnt.c] [ifnt.e] [ifnt.t])
(if (eval [ifnt.c])
(eval [ifnt.t])
(eval [ifnt.e])))
Which is "safe" because it uses unique names. Good news is that you do not need to use my
set-protected1 or to write your own - as conan wrote, Newlisp provides "contexts" which do that for yourself. Look on this REPL communication.
Code: Select all
> (context 'ifnt)
ifnt
ifnt> (define-macro (ifnt:ifnt c e t)(if (eval c) (eval t) (eval e)))
(lambda-macro (c e t)
(if (eval c)
(eval t)
(eval e)))
ifnt> (context 'MAIN)
MAIN
> (ifnt (< 2 3) ">=" "<")
"<"
> ifnt:ifnt
(lambda-macro (ifnt:c ifnt:e ifnt:t)
(if (eval ifnt:c)
(eval ifnt:t)
(eval ifnt:e)))
>
It is probably exactly what you need. It is also recommended approach by designer of the language.
Neither
set-protected1 nor
contexts are "safe" in one very special case - if recursive macro passes one of its variables as free variable from one instance of the macro to another instance of the same macro, where it will be accessed inside new binding of the same variable. It is so rare case that I never encountered something like that, and as it was discussed on this forum, it turned that noone reported that he experienced that problem.
If problem is still interesting from theoretical point of view, you can look at my blogpost
http://kazimirmajorinc.blogspot.com/200 ... exprs.html
It contains implementation of
set-protected1 and
set-protected2, last does exactly what you proposed "function to construct a function-local-context to store the function local variable, and auto destroy while the function end", which turns to be relatively complicated from technical point of view. I must warn it is not how typical "production code" looks like, it is how it looks if one wants to play with Lisp.