Pseudo-closures using gensym

Q&A's, tips, howto's
Locked
William James
Posts: 58
Joined: Sat Jun 10, 2006 5:34 am

Pseudo-closures using gensym

Post by William James »

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

Re: Pseudo-closures using gensym

Post by William James »

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:

Re: Pseudo-closures using gensym

Post by Lutz »

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

Re: Pseudo-closures using gensym

Post by William James »

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

Re: Pseudo-closures using gensym

Post by William James »

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:

Re: Pseudo-closures using gensym

Post by Lutz »

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.

Locked