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

Reply via email to