[plt-dev] `unsafe-fl' and unboxing
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