This will do the trick:

(define (assert-flonum! who x)
  (let* ((arguments (call/cc (lambda (return) (cons return x))))
         (return (car arguments))
         (x (cdr arguments)))
    (with-restart
     'use-value
     "Retry with a flonum."
     (lambda (new-value) (return (cons return new-value)))
     (lambda ()
       (prompt-for-evaluated-expression "New value"))
     (lambda ()
       (if (flonum? x)
           x
           (error:wrong-type-argument x "flonum" who))))))

The identifier retry is replaced with return since the former wasn't bound,
and values is replaced as interactor with the
prompt-for-evaluated-expression thunk. I also replaced the unless with an if
so that assert-flonum! would always return a value, although that isn't
necessary.

But this is simpler:

(define (assert-flonum! who 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)))))))

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 an example of it in use:

1 ]=> (assert-flonum! 'who 1)
;The object 1, passed as an argument to who, is not a flonum.;To
continue, call RESTART with an option number:; (RESTART 2) => Prompt
for a new flonum value.; (RESTART 1) => Return to read-eval-print
level 1.
2 error> (restart 2)


New value: 'a
;The object a, passed as an argument to who, is not a flonum.;To
continue, call RESTART with an option number:; (RESTART 3) => Prompt
for a new flonum value.; (RESTART 2) => Return to read-eval-print
level 2.; (RESTART 1) => Return to read-eval-print level 1.
3 error> (restart 3)


New value: 1.0
;Value: 1.
1 ]=>

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

Reply via email to