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] |
Per Bothner <bothner@cygnus.com> writes: > > For instance, when you spawn a new thread, which of the original > > threads' bindings should be shared with the new thread? > > They are all shared, until the new thread does another fluid-let. Right. Bindings created with fluid-let are thread local, so you have to use a different binding form to change the value of a truly global variable. And you have to sprinkle the knowledge about which vars should be handled with which binding form all over the code, every time a binding of one of these variables is made. Ugh. This makes code reuse harder, and it's ugly, and that's why the parameter abstraction is useful. > > One can imagine for instance that the current output port could be shared > > between the two threads. It's not hard to imagine other uses: > > let's say you have a cl-style parameter *print-circle*, one might > > want to have this shared across threads, and have changes to it > > automatically protected with a mutex. > > But it is harder to imagine a use that is not handled by fluid-let. Yes, but will it be _tedious_ to use fluid-let? What do you think about my comment above, about where in the code you have to specify the type of binding? It's a waste of brain power to require the programmer to remember always and everywhere whether a global variable should be shared across threads or not. > > Having an abstraction like this is very powerful, and I expect that it > > would allow other important features to be implemented easily and > > cleanly. > > Please show me a useful example that I can't do with fluid-let. "Can't do" is not a very useful benchmark, because design is always a question of convenience/aesthetics. You can write your programs in assembly, and do just fine without parameters, and I can't really argue with that. But it doesn't mean that parameters aren't a great feature for a multi-threaded Scheme. A perhaps better question is, do parameters provide a useful and well designed abstraction that fluid-let does not provide? You didn't expend the least bit of effort trying to answer that question. I'll try to formulate an example using *print-circle*. Imagine a program with two threads, operating on a circular data structure. Thread a determines that there is a chance that the data structure is circular, so it tries to prepare the world like this: (fluid-let ((*print-circle* #t)) (do-stuff-with-obj) (put-object-onto-b-inq obj) (wait-for-b-to-finish-processing obj)) Now thread b will take over, but it won't necessarily have *print-circle* set to #t. So I guess I just wanted to use *print-circle* as a global var, which changes the above to: (dynamic-wind (lambda () (set! *print-circle* #t)) (lambda () (do-stuff-with-obj) (put-object-onto-b-inq obj) (wait-for-b-to-finish-processing obj)) (lambda () (set! *print-circle* #f))) Now I want to reuse the above code in another application where *print-circle* should not be shared, but should be thread-local. Doh! With parameters, this code would be: (parameterize ((*print-circle* #t)) (do-stuff-with-obj) (put-object-onto-b-inq obj) (wait-for-b-to-finish-processing obj)) And it would work whether the user wanted *print-circle* shared across threads or not. Your point is correct of course: you can code the above without parameters. It's just ugly, difficult to reuse, and an unnecessary burden on the programmer. I'm not completely happy with the example I formulated, but I still think that this feature is very useful. It unifies the concepts of binding thread-local and truly global variables, which makes the code that uses these types of variables simpler. -russ -- "It seems certain that much of the success of Unix follows from the readability, modifiability, and portability of its software." -- Dennis M. Ritchie, September, 1979