Ok, I have felt your punches against the idea and have thought about it somewhat more.
1. I can only conclude that today it's already difficult to reason about code with respect to multiple restarts of continuation and the main reason is that at least I have been sloppy to add a ! to the macros that use set! internally. To a fun example: I have been pondering to poer common-lisp iterate for fun to learn and enjoy guile. In there they have generators e.g. (generati i ...) and then take out the values with (next i) construct. For a simple i = 1 ... one would expand next i to (begin (set! i (+ i 1)) i). So next is really next!. So this will not mix well with undo and redo. It's possible to define i as a special variable though and you will get the feature of proper undo redo support but now another problem appears we will as Mark and Daniel introduce i into any uses of next i in user and can get hard to reason about properties when the value is put into a lambda. So next is not next or next! but what? maybe next~ To indicate that lambdas that include this must expect to mutate when one does a redo!. Conventions like this is problematic because coders will most certainly be sloppy to follow this convention resulting in a mess. One really long for a type system to help clarify the matters here. Typically macro writers that post a binding a, might want users to use the underlying a~, variable as well and it would probably be good practice to let users refer to this at will e.g. reference it with (~ a), set it with (set~ a 1) as well as (set! a 1) and refer to it with e.g. a just as ordinary scheme. I would suggest that both reference a variable with set!,a, and with set~, (~ a) should be an error. Otherwise if the macro writer manages the macro correct and basically uses a user guard that we should provide e.g. (with-user (a) user-code ...) especially this means that if a is set! ed then we know that redo undo cannot work and we will force the underlying variable to be a usual variable. To accomplish this I would formulate the semantics as follows. Consider * k, the r5rs continuation * dynamic-wind, r5rs dynamic wind with the addition that k is an argument to the rewinder. Introduce (with-special ((a:id kind:object) ...) code ...) and (set~ a:id v:obj) Let self identifying the dynamic wind object lexically Introduce (special-set! self k value) (special-ref self k) Also define (guard-special? k kind) A setter and a getter of an object indexed by self and k Then the semantic for with-special in guard mode would be (let ((last #f)) (dynamic-wind (lambda (k) (when (guard-special? k kind) (set! a (special-ref self k)))) (lambda () (call-with-values (lambda () (begin code ...)) (lambda ret (set! last #t) (apply values ret)))) (lambda (k . l) (unless last (special-set! self k a)))) Guard mode is entered only if a is referenced with set~ and never with set! if it can be proved Otherwise guard mode is never entered. The semantics of set~ is the same as with set! otherwise. if with-special is not in guard-mode then it behaves just as (let () code ....) I really hope that I mange to converge a good concept with this discussion! WDYT On Thu, Mar 21, 2013 at 8:03 PM, Mark H Weaver <m...@netris.org> wrote: > Stefan, you're still describing your proposal in terms of low-level > implementation details such as stacks. In the general case, we cannot > store environment structures on the stack. Furthermore, in the general > case *all* variables in scheme are bound to locations, not values. Only > in special cases can we use stacks, and only in special cases can we > avoid boxing variables. These are only _optimizations_. > > If you're serious about this proposal, please read sections 3.1 and 3.4 > of the R5RS carefully. Explain your proposed _semantics_ (not the > implementation details) in those terms, where *all* variables are bound > to _locations_, and where there is no stack at all (everything is > conceptually stored in a garbage-collected heap). > > We need to understand the *semantics* in the simplest possible terms > before we even begin to think about how to implement it. > > Thanks, > Mark