"R. Kent Dybvig" <dyb_at_cs.indiana.edu> writes:
>> However, parameters are neither simple nor general.
>
> Here is an implementation of make-parameter and parameterize in about 20
> lines of r5.92rs code. Adding thread parameters requires an additional
> few lines of nonstandard code. I suppose whether you'd call the code or
> the mechanism it implements "simple" is a matter of taste, but it is
> simple to me.
> [...]
> (define-syntax parameterize
> (lambda (x)
> (syntax-case x ()
> [(_ ((x v) ...) e1 e2 ...)
> (with-syntax ([(p ...) (generate-temporaries #'(x ...))]
> [(y ...) (generate-temporaries #'(x ...))])
> #'(let ([p x] ... [y v] ...)
> (let ([swap (lambda () (let ([t (p)]) (p y) (set! y t)) ...)])
> (dynamic-wind #t swap (lambda () e1 e2 ...) swap))))])))
What's the four-argument version of `dynamic-wind'?
> The generality derives from the fact that a parameter is a procedure and,
> when the parameter is referenced or set, directly or through parameterize,
> it can do anything one can imagine a procedure doing.
The problem is that seemingly simple code can have complex behavior.
In this case, the complexity derives from `swap'. As I mentioned
earlier, one desirable characteristics of dynamically-bound variables
is that a continuation captures their values. In your design, the
continuation neither captures the values nor the locations, but
instead captures *actions* (involving `swap') leading to the current
values. If swapping were replaced by the even simpler restoration of
the previous value like so (sorry, once again my `syntax-case' kung-fu
does not hack it, so it's `syntax-rules' and one parameter only):
(define-syntax paramize
(syntax-rules ()
((paramize ((?name ?val)) ?body ...)
(let ((p ?name))
(let ((previous (p))
(val ?val))
(dynamic-wind
(lambda () (p val))
(lambda () ?body ...)
(lambda () (p previous))))))))
... you get different semantics. So the implications are subtle, at
least sufficiently subtle for me to have trouble gauging their effect
on programs.
> Anyway, didn't you just complain that parameters are too general?
Yes. So?
>> Moreover, the particular design you chose is problematic because it
>> destroys modularity.
>
> You've offered no evidence to this effect here or in your Scheme workshop
> paper, which does not anticipate the design.
The paper doesn't anticipate anything. The authors did, however. If
I understand the semantics of Chez's parameters with respect correctly
(I probably still don't), then the scenario section 5.3 of the paper
applies. If it doesn't, I hope you'll enlighten me.
> From what I can make out of the rather vague concept in your paper,
> I don't think the design does destroy modularity.
>
> While reasoning about programs that both parameterize and directly modify
> parameters might be difficult, especially when escape procedures and
> threads are involved, this is no more so than for other effects.
Right. Which is why an effect-less version of dynamic binding has
simple semantics.
> If the effects are the problem, you can build an abstraction layer that
> prohibits direct mutation and thus preserves whatever modularity you think
> has been destroyed. Including the general mechanism and allowing people
> to create restricted abstractions seems more in the spirit of Scheme than
> including one or more of the restricted abstractions.
While I this is a weird interpretation of the "spirit of Scheme" by
me, the problem goes deeper: Mutation is insidious in that, operating
behind the scenes, it breaks through abstractions. Take the (r6rs
mutable-pairs) library: Abstracting over it is not enough to get the
benefits of its absence.
>> In contrast, dynamic binding as a separate
>> mechanism is simple and modular. Combined with thread-local storage
>> (less simple and not modular, but still simpler than parameters), you
>> can build parameters.
>
> I don't see how you could build the full generality of parameters and
> parameterize---please enlighten me. It would be enough to demonstrate it
> for the single-threaded world using mutable variables or objects in place
> of thread-local storage, i.e., any storage that's local to the single
> thread of a single-threaded system. If you actually can implement
> parameterize and mutable parameters using your dynamic value binding and
> some form of state, I wonder in what sense your dyanmic value binding
> actually preserves the modularity you want.
I'm still unsure of the semantics of Chez's `parameterize'
wrt. threads, so I'll probably get it wrong at first try. Here's it,
in terms of your code:
(define make-parameter
(case-lambda
[(init guard)
(let ([v (make-thread-cell (guard init))])
(case-lambda
[() v]
[(u) (thread-cell-set! v (guard u))]))]
[(init) (make-parameter init values)]))
--
Cheers =8-} Mike
Friede, V?lkerverst?ndigung und ?berhaupt blabla
Received on Wed Feb 21 2007 - 02:20:57 UTC