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] |
Russell McManus <mcmanus@IDT.NET> writes: > My attempt seems to work; give it a whirl and let me know if you > agree. Your macro is fine for the usual case of single-entry/single-exit. But with the full power of continuations, it can actually happen that the flow of control enters your BODY (gives a nice chill down the back), leaves it temporarily, and then reenters it. This would happen when you implement coroutines with continuations, say. Each of the coroutines should be able to have their own fluid-let active and they should not interfere. Now, with your implementation, the fluid variables are correctly restored to the values that they have outside of the fluid-let, but when the flow of control returns, they are again set to the *initial* values specified in the flui-let form and not to the values they had inside the fluid-let when the flow of control left. In addition, the external values are not saved when we reenter the fluid-let. Thus, when we leave it a second time, the fluid variables are *again* restored to the values they had when entering the fluid-let for the first time. In essence you simply want to keep a backup copy of the values of the fluid variables and swap these backup values with the variables both on entering and leaving the fluid-let. That is, when the flow of control is inside the fluid-let, the backup copy would hold the values that the fluid variables had outside the fluid-let; and when the flow of control is outside the fluid-let, they hold the values for inside until the flow returns. Like, for a single variable: (define-macro (swap x y) (let ((t (gensym))) `(let ((,t ,x)) (set! ,x ,y) (set! ,y ,t)))) (define-macro (fluid-let bindings-ls . body) (let ((id (caar bindings-ls)) (val (cadar bindings-ls)) (backup (gensym))) `(let ((,backup ,val) (body (lambda () ,@body))) (let ((swapper (lambda () (swap ,id ,backup)))) (dynamic-wind swapper body swapper))))) When extending this to more than one variable, one should be careful to make fluid-let actually like `let', and not like `letrec', like your code does (by using `define'). > The question I have is: how would one do this with > (make-fluid) instead of (gensym) so that this would work with threads? > Is it really basically just a couple of substitutions? Rewriting this to use Guile's fluids would give you `with-fluids'. You still can't access the fluid objects like normal variables (because they are not normal variables). In fact, when we have generalized variables on could simply write (fluid-let ((fluid the-current-module-fluid) my-module) <do stuff with my-module being current>) Having to use `(fluid-ref x)' instead of just `x' all over the place is inconvenient, but solving this is purely a syntax issue in my view. When we do solve it, by implementing symbol-macros for example, we should not restrict the solution to fluids. The same thing (implicit setters/getters) is needed for variable traces. [Doesn't syntax-case already have symbol-macros?]