<br><div><span class="gmail_quote">On 6/13/07, <b class="gmail_sendername">Jens Axel Søgaard</b> <<a href="mailto:jensaxel@soegaard.net">jensaxel@soegaard.net</a>> wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>> The imported names are bound to values. Somewhere and at some time<br>> these values must have been evaluated. To run a piece of code,<br>> it must be expanded first. Since macros and what they depend on live
<br>> in the transformation environment, values and structure definitions<br>> are needed in the transformer environment before they are needed<br>> in the runtime environment. One could argue that the values in the
<br>> transformer enviroment could be reused in the runtime environment<br>> (that's what the defmacro system does), but that leads to a number<br>> of problems. Problems that disappear, when the the runtime and the
<br>> transformer environment are separated.</blockquote><div><br>I've seen the paper that describe this issue and the solution seems pragmatic, but my guess is that this is an edge case where a computed struct value is not usable - because I didn't find a disclaimer that says "don't return struct from macro - you can't use it" ;)
<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">> *Maybe* the following technique can be used. The example features<br>> structures in structures. A square consists of four points. The
<br>> macro (create-square n) calculates at expansion time the coordinates<br>> of the four corners of a square with side length 2*n (just to<br>> show an actual computation takes place).</blockquote><div><br>Thanks Jens for the novel idea - I know you are not recommending this approach, and for now I will go back to the old way and not use macro to return structs.
<br><br>I tried another approach - i.e. returning the transformation-bound struct functions to run-time, and it works. However, generalizing the solution seems unwieldy, so until this is addressed at language level, the disclaimer above is valid ;) Below is a sketch of the idea:
<br><br>(module foo mzscheme <br> (define-struct foo (vals) (make-inspector))<br> (provide (all-defined)))<br>(require-for-syntax foo)<br>(define-syntax (macro-foo stx)<br> (syntax-case stx ()<br> ((_ val1 val2 ...)
<br> (with-syntax ((val (datum->syntax-object<br> #'_<br> (make-foo (syntax-object->datum #'(val1 val2 ...))))))<br> #'val))))<br>;;; returns the struct functions from transform env to run-time
<br>(define-syntax (require-foo-struct stx) <br> (syntax-case stx ()<br> ((_)<br> (with-syntax (((struct:foo make-foo foo? foo-vals set-foo-vals!)<br> (datum->syntax-object <br> #'_
<br> (map (lambda (name)<br> (datum->syntax-object #'_ name))<br> '(struct:foo make-foo foo? foo-vals set-foo-vals!))))<br> ((s make isa? vals set-vals!)
<br> (datum->syntax-object<br> #'_<br> (list struct:foo make-foo foo? foo-vals set-foo-vals!))))<br> #'(define-values (struct:foo make-foo foo? foo-vals set-foo-vals!)
<br> (values s make isa? vals set-vals!))))))<br>(require-foo-struct) ; get the copy of the struct functions <br>(define f1 (macro-foo 1 2 3))<br>foo? ; #<primitive:foo?><br>f1 ; #(struct:foo (1 2 3))<br>(foo? f1) ; #t
<br>(foo-vals f1) ; '(1 2 3)<br><br></div></div>