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,
dynamically scoped.
> 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...)
cheers,
felix