[plt-scheme] create complex object @ compile time but made available @ run time?

From: YC (yinso.chen at gmail.com)
Date: Wed Jun 13 14:19:40 EDT 2007

On 6/13/07, Jens Axel Søgaard <jensaxel at soegaard.net> wrote:
> > The imported names are bound to values. Somewhere and at some time
> > these values must have been evaluated. To run a piece of code,
> > it must be expanded first. Since macros and what they depend on live
> > in the transformation environment, values and structure definitions
> > are needed in the transformer environment before they are needed
> > in the runtime environment. One could argue that the values in the
> > transformer enviroment could be reused in the runtime environment
> > (that's what the defmacro system does), but that leads to a number
> > of problems. Problems that disappear, when the the runtime and the
> > transformer environment are separated.

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" ;)

> *Maybe* the following technique can be used. The example features
> > structures in structures. A square consists of four points. The
> > macro (create-square n) calculates at expansion time the coordinates
> > of the four corners of a square with side length 2*n (just to
> > show an actual computation takes place).

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.

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:

(module foo mzscheme
  (define-struct foo (vals) (make-inspector))
  (provide (all-defined)))
(require-for-syntax foo)
(define-syntax (macro-foo stx)
  (syntax-case stx ()
    ((_ val1 val2 ...)
     (with-syntax ((val (datum->syntax-object
                         (make-foo (syntax-object->datum #'(val1 val2
;;; returns the struct functions from transform env to run-time
(define-syntax (require-foo-struct stx)
  (syntax-case stx ()
     (with-syntax (((struct:foo make-foo foo? foo-vals set-foo-vals!)
                     (map (lambda (name)
                            (datum->syntax-object #'_ name))
                          '(struct:foo make-foo foo? foo-vals
                   ((s make isa? vals set-vals!)
                     (list struct:foo make-foo foo? foo-vals
       #'(define-values (struct:foo make-foo foo? foo-vals set-foo-vals!)
           (values s make isa? vals set-vals!))))))
(require-foo-struct) ; get the copy of the struct functions
(define f1 (macro-foo 1 2 3))
foo? ; #<primitive:foo?>
f1 ; #(struct:foo (1 2 3))
(foo? f1) ; #t
(foo-vals f1) ; '(1 2 3)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20070613/139e2211/attachment.html>

Posted on the users mailing list.