[plt-scheme] call/cc, set!, and fluid-let

From: Eli Barzilay (eli at barzilay.org)
Date: Wed Jun 15 11:02:45 EDT 2005

On Jun 15, Jay McCarthy wrote:
> > 2) I don't understand why you need a thing like this for the situation
> > you're describing.  I think I would just use a tail-call. Here's
> > how I would structure the code, if I understand you correctly:
> > 
> > (define (sorting-proc-a l) ...)
> > (define (sorting-proc-b l) ...)
> > (define (sorting-proc-c l) ...)
> > 
> > (define (show-list l)
> >    (send-suspend/callback-thingy (make-page l)
> >       ; if user clicks "sort a":
> >       => (show-list (sorting-proc-a l))
> >       ; if user clicks "sort b":
> >       => (show-list (sorting-proc-b l))
> >       ; if user clicks "sort c":
> >       => (show-list (sorting-proc-c l))
> >       ; if user clicks something else:
> >       => (call-to-somewhere-else ...)))
> Add to this example that reclicking "sort a" goes in reverse, and
> that clicking "sort a", "sort b" causes the list to be sorted by b
> with a as the tie breaker. See how the code needs
> future-of-the-computation state.

I don't see any future state that is needed.  The thing with
continuations is that they capture the current stack state, so as long
as you keep all state as lexical values things should be fine.  I'd
try something like this which does just that:

  ;; a comparer is: A A -> bool

  (define (comparing-proc-a x y) ...)
  (define (comparing-proc-b x y) ...)
  (define (comparing-proc-c x y) ...)

  (define ((reverse-comparer compare) x y)
    (compare y x))

  (define (add-comparer c comparers)
    (if (and (pair? comparers) (eq? c (car comparers)))
      ;; it was already first, so reverse it
      (cons (reverse-comparer c) (cdr comparers))
      ;; add as a first comparer, remove any other instances
      (cons c (remove c comparers))))

  (define (show-list l comparers)
    (send-suspend/callback-thingy (make-page l comparers)
      ; if user clicks "sort a":
      => (show-list l (add-comparer comparing-proc-a comparers))
      ; if user clicks "sort b":
      => (show-list l (add-comparer comparing-proc-b comparers))
      ; if user clicks "sort c":
      => (show-list l (add-comparer comparing-proc-c comparers))
      ; if user clicks something else:
      => (call-to-somewhere-else ...)))

> Furthermore, Sorting is just an example. For any given example you
> can change make it work in a particular instance, if you are willing
> to accept the pain. But if you want to have an embeddable component
> library where the components may have future-of-the-computation
> state.

When you add side effects, either `set!' or `fluid-let', things will
probably break.  I think that you could use parameters (or thread
cells) which will have a value for every continuation, but it's
probably better to avoid the whole thing if possible.

          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                  http://www.barzilay.org/                 Maze is Life!

Posted on the users mailing list.