Q&A's, tips, howto's
William James
Posts: 58 Joined: Sat Jun 10, 2006 5:34 am
Post
by William James » Sun Apr 01, 2012 3:39 pm
Code: Select all
(define (gensym:gensym)
(sym (string "gensym-" (inc gensym:counter))))
(define-macro (closure varval-pairs body)
(let (alist (map (fn(x) (list (x 0) (gensym) (eval (x 1))))
(explode varval-pairs 2)))
(bind (map (fn (x) (rest x)) alist))
(dolist (x alist)
(set-ref-all (x 0) body (x 1)))
body))
(set 'up-down
(closure (a 0 b 99)
(lambda () (list (++ a) (-- b)))))
> (up-down)
(1 98)
> (up-down)
(2 97)
> (up-down)
(3 96)
> (println up-down)
(lambda () (list (++ gensym:gensym-14) (-- gensym:gensym-15)))
William James
Posts: 58 Joined: Sat Jun 10, 2006 5:34 am
Post
by William James » Wed Apr 04, 2012 2:22 pm
Slightly improved, and with an example in which two lambdas share a variable.
Code: Select all
(define-macro (closure varval-pairs)
(let (body (cons 'begin (args))
alist (map (fn(x) (list (x 0) (gensym) (eval (x 1))))
(explode varval-pairs 2)))
(bind (map (fn (x) (rest x)) alist))
(dolist (x alist)
(set-ref-all (x 0) body (x 1)))
(eval body)))
(closure (count 0)
(setq up (fn()(++ count))) (setq down (fn()(-- count))))
: (up)
1
: (up)
2
: (up)
3
: (down)
2
: (down)
1
Lutz
Posts: 5289 Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:
Post
by Lutz » Wed Apr 04, 2012 3:09 pm
Nice application of 'gensym'.
For a different way of doing it see here:
http://www.newlisp.org/index.cgi?def-static
The difference to WJ's solution is, that it puts each function in it's own namespace via a default functor.
William James
Posts: 58 Joined: Sat Jun 10, 2006 5:34 am
Post
by William James » Wed Apr 04, 2012 8:49 pm
Thanks. I think it would be nice if gensym were built into newLISP.
William James
Posts: 58 Joined: Sat Jun 10, 2006 5:34 am
Post
by William James » Tue Apr 10, 2012 5:03 pm
It seems that gensym isn't really needed anymore.
One can simply do (sym (uuid)).
Lutz
Posts: 5289 Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:
Post
by Lutz » Tue Apr 10, 2012 5:18 pm
Yes, that works well and those things are unique ;-) On the other side the gensym function, you are using, is slightly faster and keeps the generated symbols all in the special gensym namespace. But if you are only using a few than (sym (uuid)) is more practical. Personally, I just move define-macro's (fexprs) into their own namespace, which also solves variable capture, and creates some sort of lexical closure.