> Date: Thu, 30 Jul 2026 16:39:28 -0700
> From: "Arthur A. Gleckler" <[email protected]>
> 
> I also replaced the unless with an if so that assert-flonum! would
> always return a value, although that isn't necessary.

I think you'll find it is rather necessary if you want to actually
_use_ the replacement!

> That still captures a continuation every time around, even when there is no
> error. This duplicates a tiny bit of code, but would be faster:
> 
> (define (assert-flonum! who x)
>   (if (flonum? x)
>       x
>       (call-with-current-continuation
>        (lambda (escape)
>          (with-restart
>           'retry-flonum
>           "Prompt for a new flonum value."
>           (lambda (x*) (escape (assert-flonum! who x*)))
>           (lambda () (prompt-for-evaluated-expression "New value"))
>           (lambda ()
>             (if (flonum? x)
>                 x
>                 (error:wrong-type-argument x "flonum" who))))))))

Here's a further likely improvement in performance (caveat: untested):

(define-integrable (assert-flonum! who x)
  (let loop ((x x))
    (if (flonum? x)
        x
        (loop (restartable-error:not-flonum who x)))))

(define (restartable-error:not-flonum who x)
  (call-with-current-continuation
   (lambda (escape)
     (with-restart 'retry-flonum "Prompt for a new flonum value."
         escape
         (lambda () (prompt-for-evaluated-expression "New value"))
       (lambda ()
         (error:wrong-type-argument x "flonum" who))))))

This way, the type check can be done in-line in callers, while the
error path is out-of-line.

> But take all of this with a grain of salt because I'm a novice at using the
> restart system.

In practice, I haven't found restarts to be particularly useful -- I
don't think I have ever actually used them except while playing around
to see how they work.  Generally, I find there are two better
approaches:

1. making a computation cheap to reproduce from all its inputs so you
   can start it over from the beginning with one input tweaked, and/or

2. making a costly computation checkpoint its state so you can easily
   roll back to a checkpoint and pick up where it left off -- either
   because of a bug, or because you got bored and hit ^G, or because
   of a power outage, or because you wanted to move to a faster
   machine without losing your progress.

Reply via email to