This is the mail archive of the guile@cygnus.com mailing list for the guile project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Marius Vollmer <mvo@zagadka.ping.de> writes: > Russ McManus <mcmanr@eq.gs.com> writes: > > > Is this closer? > > Yep. You might want to look at fluidlet.scm from SLIB and see how > they do it with syntax-rules macros. You might also note (as I have > just this moment) that `fluid-let' from SLIB does not save the > external values on reentry, which I find strange. What do you say, is > it a bug in SLIB? Well, if you were right before, and you're right about the slib code, then slib indeed has a bug in it. (Hmmm. That wasn't very helpful). Actually I purposefully avoided looking at anyone else's code, so that I could get some practice writing a non-trivial macro. Obviously, once you know the concepts, it makes sense to learn from others' code. > > (defmacro fluid-let (binding-ls . body) > > (let* ((expanded-binding-ls > > (map (lambda (binding) > > (append binding (list (gensym)))) > > You might want to put the gensym first, with (cons (gensym) binding). This was actually a conscious choice. In my (perhaps twisted) mind, the variable name is the 'car' of a binding, and it's value is the 'cadr', so I didn't want to confuse myself. > > binding-ls)) > > (tmp-var (gensym)) > > (environment-ls > > (map (lambda (binding) > > `(,(caddr binding) ,(cadr binding))) > > expanded-binding-ls)) > > (swap-ls > > (map (lambda (binding) > > `(begin > > (set! ,tmp-var ,(car binding)) > > (set! ,(car binding) ,(caddr binding)) > > (set! ,(caddr binding) ,tmp-var))) > > Binding temp-var with `let' might be cleaner here. Since I was using 'set!' willy-nilly, I just kept going. See below for version with 'let'. > `(let ((,tmp-var ,(car binding))) > (set! ,(car binding) ,(caddr binding)) > (set! ,(caddr binding) ,tmp-var)) > > > expanded-binding-ls))) > > `(let ,environment-ls > > (let ((,tmp-var #f)) > > (dynamic-wind > > (lambda () ,@swap-ls) > > (lambda () ,@body) > > (lambda () ,@swap-ls)))))) > > I think there is no need to duplicate the (lambda () ,@swap-ls), just > make one closure outside of the dynamic-wind. Wow. You rule. > > Now on to with-fluids... > > And after that you might want to try to express fluid-let with > defmacro but *without* gensym, while still being referential > transparent. <ignorance> Why is it important to get rid of gensym? Where can I find an understandable definition of 'referential transparency'? </ignorance> Take three on fluid-let, with all your suggestions (I hope I didn't bungle this one): (defmacro fluid-let (binding-ls . body) (let* ((expanded-binding-ls (map (lambda (binding) (append binding (list (gensym)))) binding-ls)) (tmp-var (gensym)) (environment-ls (map (lambda (binding) `(,(caddr binding) ,(cadr binding))) expanded-binding-ls)) (swap-form `(lambda () ,@(map (lambda (binding) `(let ((,tmp-var ,(car binding))) (set! ,(car binding) ,(caddr binding)) (set! ,(caddr binding) ,tmp-var))) expanded-binding-ls))) (swap (gensym))) `(let ,environment-ls (let ((,swap ,swap-form)) (dynamic-wind ,swap (lambda () ,@body) ,swap))))) It seems to be getting shorter. I guess that's Scheme for 'ya. -russ -- mainstream, adj. fanatically opposed to anything at all unusual.