[plt-dev] `unsafe-fl' and unboxing

From: Ryan Culpepper (ryanc at ccs.neu.edu)
Date: Sun Oct 4 18:42:33 EDT 2009

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



Posted on the dev mailing list.