This page is part of the web mail archives of SRFI 39 from before July 7th, 2015. The new archives for SRFI 39 contain all messages, not just those from before July 7th, 2015.
Hello, guys. I'm coming to this discussion somewhat late. Bravo, Marc, for tackling this one. SRFI says: A parameter object created by the procedure make-mutable-parameter is a procedure which accepts zero or one argument (what happens when two or more arguments is given is completely implementation dependent). A parameter object created by the procedure make-parameter is a procedure which accepts no argument (what happens when one or more argument is given is completely implementation dependent). Why do we say extra args to a parm object is undefined? Why not error? Why is PARAMETERIZE syntax? Make it a function, and render all issues of eval-order irrelevant. Having captured the core idea as a procedure, then define a litle piece of binding syntax in terms of it: (paramterize param val thunk) ; Procedure (let-parameter ((param val) ...) body ...) ; Derived syntax (let-parameter* ((param val) ...) body ...) ; Derived syntax Or punt the macros and just stick to basic functionality. Why is the PROMPT mutable param implementation-dependent when passed "> "? It seems like it's definitely defined, since it's a mutable parameter, to alter the binding to "> ". Am I missing something here? Matthew asked "Why mutable params?" I support them, with the *exact* semantics Marc provides -- threads *inherit* the dynamic bindings. This allows thread code to be written that interacts w/other threads via shared state accessed from a parameter. The agent that forks off the threads controls the degree of sharing or insulation by arranging sharing of parameter cells. For example, consider a cursor-like object, such as a "current working directory" or a pointer into a database table. Two threads might want to move around in the directory structure or the table by altering the cursor. One thread changes the cursor, the other sees it. You arrange this by (1) binding the param to a fresh cell, then (2) spawning two threads in the single dynamic scope of that binding. Suppose, however, you want *independent* thread groups. No trouble there, either. You just spawn each thread or cooperating thread group in a different dynamic-parameter binding. So you have complete control of this kind of thing, and the degree of sharing doesn't show up in the thread code itself. You can take the same code, and run it in isolated solitude, in a group of two, a group of twenty, whatever you like. In general, *any* kind of thread-global shared resource (like the typical radix & standard-io examples) fits nicely into this scheme. I know Mike S & Kelsey prefer to reset dynamic bindings to fresh bindings with top-level values at thread-spawn boundaries. I think this is completely broken. Spawning a thread, calling a function -- it's a dynamic nesting. I readily admit you can implement mutable params with immutable params and a one-elt vector. But I also buy Marc's story that this is not "the way of Scheme" -- you could also "implement" mutable *variables* with immutable vars & one-elt vectors, but Scheme doesn't. Also, if you emulate mutable params with immutable params + mutable cells, you *expose the cell to parameter clients* -- when you just want to expose the *value of the cell*. This can lead to bugs, in the general way bugs happen when you expose the underlying encoding of a thing (e.g., you encode a structure as a three-element list or something like that). Providing mutable params as a primitive locks up the internal cell so buggy clients can't accidentally fetch it out, store it away, pass it around, reference it outside of scope, etc. Sound like an abstract objection? It's pretty concrete, actually, by which I mean that it's not an unrealistic bug -- it's the kind of bug you would expect to see in real code. The bug will be someone fetching the cell from the param and forgetting to dereference it, so the mutable cell, intended to be internal to the param, will propagate through the program the way the cell's value was intended to propagate. I do not like the whole idea of packaging up this functionality as procedures; I'd rather they be a new data type. But Marc has motivated his decision to do this -- staying close to existing APIs while focussing on the tricky semantic decisions. I can roll with that, and won't even complain about how much I hate the ambiguous, confusing term "parameter." -Olin