[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Some comments
Marc Feeley wrote:
This is unfortunate, since this SRFI really moves all that "legacy"
code into non-specifiedness...
Since SRFI 39 did not exist when the legacy code was written the code
never conformed to it. So SRFI 39 does not "move" the code into
non-specifiedness. The other choice (of having "make-parameter"
create the mutable parameters as specified in SRFI 39) is even less
appealing because in that case PLT legacy code would no longer work if
PLT adopted that semantics.
That is exactly the reason why I think having fully thread-local
parameters is the more practical solution. The "legacy" code I talk of
is the (perhaps not unconsiderable) amount of code written that uses
parameters that do not share their value among different threads
(as in PLT).
I think parameters (as used in Chez, PLT or (say) Chicken) are
(IMHO) well understood and heavily used.
For these systems and Gambit-C, "make-mutable-parameter" and
"make-parameter" can be defined as the native "make-parameter" when
multithreading is not used. The semantic differences only matter with
PLT when threads are being used and the parameters are mutated (indeed
only PLT and Chicken implement threads and the Chicken manual does not
explain the interaction between parameters and threads).
[It does, albeit not explicitly enough (see the SRFI-18 section).
I will fix this.]
I view SRFI
39's main contribution as a specification of how mutation of
parameters should work in the presence of threads.
Absolutely. But I think one should be more pragmatic here and
use parameters as user-defined *fully* thread-local storage,
No "copy-on-write" is not a valid implementation. The reason is that
the "swapping" semantics requires the child thread to have an
independent copy of the parent's thread. So the child must get a
snapshot of the parent's dynamic environment which will make the
child's mutations invisible to the parent ***AND*** the parent's
mutations invisible to the child. The copy-on-write approach you
suggest only makes the child's mutations invisible to the parent.
That's not true. I'm probably expressing myself not clearly enough.
`make-parameter' creates a parameter in a global environment (not attached)
to any thread. Thread-creation copies the parent's parameter-env,
*but* this env will be empty if the parent has not yet changed it's
parameter-env (i.e. it is equivalent to the global env).
I'm pretty sure that it works. I would be delighted to see some sample
code that demonstrates the problem.
When I say "clean" I don't mean it so subjectively. A strong argument
can be made that the semantics I propose in SRFI 39 for dynamic
binding are closer to the lexical binding semantics. What does this
mean? Well, if you look at how environments are manipulated in the
denotational semantics (section 7.2 of R5RS) you will see that there
are only two operations on environments "lookup" and "extends".
"lookup" returns the location in the store that is bound to an
identifier. The value associated to a location in the store is
obtained with "hold" and "assign" changes the value associated with
the location. Dynamic binding as I propose it uses exactly the same
operations (with the minor point that the domain of "lookup" and
"extends" must be changed to accept parameter objects). In addition
to the lexical environment, the semantic functions also need an extra
environment: the dynamic environment. The dynamic binding semantics
is simply obtained by having procedure call pass this dynamic
environment to the called procedure (and this is the only thing that
distinguished it from lexical binding). Similarly (but obviously
outside the scope of R5RS), the creation of a new thread would capture
the dynamic environment of the parent thread. That's it. There is no
need for an additional semantic operation for copying dynamic
environments (which is non trivial because it must allocate store).
Dynamic binding is a simple and natural extension of the R5RS
Perfectly valid, but to repeat: I see parameters as a simple and effective device
for having thread-local storage, nothing more.
I find the reasons you give insufficient for changing a well-established
construct like parameters. The performance argument is weak, incompatibility
to existing systems will make adoption of this SRFI harder and compatibility
to non-released software is unimportant. Additionally it puts unneccessary burden
on implementors and confuses users of implementations that have parameters and threads.
(BTW, there is a simple way out of this dilemma: use different
names - `make-dynamic' and `let-dynamic' come to mind, for example...)