Dave Herman wrote:
;;; (real->float x) -> inexact-real?
;;; x : real?
;;; Returns an inexact real (i.e., a float) given real x. Raises an
error if x
;;; is not a real. This can be used to ensure a real value is a float,
even in
;;; unsafe code.
(define (real->float x)
(if (real? x)
(exact->inexact x)
(error "expected real, given" x)))
I'll use it to protect unsafe code. I'm sure it's more overhead than
putting it in-line, but hopefully not too much. Putting a contract on
it would probably not make much sense.
I feel a little dirty suggesting it, but you could also do:
(define-syntax-rule (real->float exp)
(let ([x exp])
(if (real? x)
(exact->inexact x)
(error "expected real, given" x))))
I'm not sure whether the mzscheme compiler obeys the Macro Writer's Bill
of Rights in optimizing the case where exp is just a variable reference.
If not, you could do the optimization yourself:
(define-syntax (real->float stx)
(syntax-case stx ()
[(_ x)
(identifier? #'x)
#'(if (real? x)
(exact->inexact x)
(error "expected real, given" x))]
[(_ exp)
#'(let ([x exp])
(real->float x))]))
No! 'identifier?' does not check whether a syntax object represents a
variable reference, given 1) identifier macros and 2) #%top transformers
for unbound variables. If you really, really want to check if something
is a variable reference, 'local-expand' it and look at the result.
But even if it is a variable reference, there's no guarantee that there
isn't another thread holding a reference to it, waiting to change it
from a real to, say a complex number right after the 'real?' check is done.
Ryan
_________________________________________________
For list-related administrative tasks:
http://list.cs.brown.edu/mailman/listinfo/plt-dev