I've used your solution 1. quite a few times, but 2. could be very useful for a few cases I'm looking into. Would it be a little like external memoization, or simpler like saving, in my case, a few matrices, and indices of the current state?
On Fri, 31 Jul 2026, 05:37 Taylor R Campbell, < [email protected]> wrote: > > 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. > >
