When I was originally thinking about it, I was thinking a macro, too. I like the real->float as an exported function for simplicity - I think most users of the science collection would be more comfortable with it in their own code. But I like the syntax of the following macro.<br>
<br><span style="font-family: courier new,monospace;">(define-syntax (with-float stx)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> (syntax-case stx ()</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> ((_ (x ...) expr ...)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> (for ((id (in-list (syntax->list #'(x ...)))))</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> (unless (identifier? id)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> (raise-syntax-error #f</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> "not an identifier"</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> stx</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> id)))</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> #`(let ((x (if (real? x)</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> (exact->inexact x)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> (error "expected real, given" x)))</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> ...)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> expr ...))))</span><br style="font-family: courier new,monospace;">
<br>It would be used in something like:<br><br><span style="font-family: courier new,monospace;">(define (test x y)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> (with-float (x y)</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> (printf "x = ~a, y = ~a~n" x y)))</span><br><br>The expr's are executed with x and y guaranteed to be floats. So, (test 10 20) prints x = 10.0 y = 20.0 and (test 10+10i 20) errors with expected real, given 10+10i. Also, the x's must be identifiers or a syntax error is raised at expansion time.<br style="font-family: courier new,monospace;">
<br>Can any of the macro gurus comment on whether this make sense? It works, but for example, there might be a cleaner way than the (syntax->list #'(x ...)) to do the iteration.<br><br><br><div class="gmail_quote">
On Sun, Oct 4, 2009 at 4:55 PM, Dave Herman <span dir="ltr"><<a href="mailto:dherman@ccs.neu.edu">dherman@ccs.neu.edu</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div class="im"><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
;;; (real->float x) -> inexact-real?<br>
;;; x : real?<br>
;;; Returns an inexact real (i.e., a float) given real x. Raises an error if x<br>
;;; is not a real. This can be used to ensure a real value is a float, even in<br>
;;; unsafe code.<br>
(define (real->float x)<br>
(if (real? x)<br>
(exact->inexact x)<br>
(error "expected real, given" x)))<br>
<br>
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.<br>
</blockquote>
<br></div>
I feel a little dirty suggesting it, but you could also do:<br>
<br>
(define-syntax-rule (real->float exp)<br>
(let ([x exp])<div class="im"><br>
(if (real? x)<br>
(exact->inexact x)<br>
(error "expected real, given" x))))<br>
<br></div>
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:<br>
<br>
(define-syntax (real->float stx)<br>
(syntax-case stx ()<br>
[(_ x)<br>
(identifier? #'x)<div class="im"><br>
#'(if (real? x)<br>
(exact->inexact x)<br></div>
(error "expected real, given" x))]<br>
[(_ exp)<br>
#'(let ([x exp])<br>
(real->float x))]))<br><font color="#888888">
<br>
Dave<br>
<br>
</font></blockquote></div><br>