[plt-scheme] Attaching compile-time information to structure types

From: Ryan Culpepper (ryanc at ccs.neu.edu)
Date: Thu Feb 21 08:20:43 EST 2008

Dave Gurnell wrote:
> Hi all,
> 
> I have another macrological question,related to but separate from my 
> last one about my SQL wrapper.
> 
> I have a macro, define-persistent-struct, that defines a struct that can 
> be serialized to a database. define-persistent-struct basically works 
> like define-struct, except it creates a few more variables. For example:
> 
>     (define-persistent-struct person ([name type:string] [age 
> type:integer]))
> 
> would define all the things that define-struct would defined:
> 
>     person, struct:person, make-person, person?, person-age, person-name 
> and so on...
> 
> plus some metadata that gets attached via a property:
> 
>    entity:person, attr:person-age, attr:person-name ...
> 
> I'd like to attach some extra compile-time information to person so I 
> can retrieve the bindings for entity:person and attr:whatever in macros.
> 
> I hacked something up by subtyping struct-info from 
> scheme/private/struct-info.ss and adding extra fields to it. This works 
> for the most part, but it is obviously not the recommended approach as 
> struct:struct-info isn't provided from struct-info.ss. I've also had 
> problems using scheme/match in certain cases.
> 
> Can anyone point me in the right direction?

The easiest way that comes to mind is to use a compile-time table 
(module-identifier-mapping) that maps struct names to the additional 
information you want.

The code would look something like the following (error-handling code 
omitted, treats types as symbols, etc):

(module persistent-struct scheme/base
   (require (for-syntax scheme/base)
            (for-syntax syntax/boundmap))

   (define-for-syntax the-table (make-module-identifier-mapping))

   (define-syntax define-persistent-struct
     (syntax-rules ()
       [(define-persistent-struct name ([field type] ...))
        (begin (define-struct name (field ...))
               (begin-for-syntax
                 (module-identifier-mapping-put! the-table #'name
                   (list (cons 'field 'type) ...))))]))

   (define-syntax (type-of-field stx)
     (syntax-case stx ()
       [(type-of-field struct field)
        (let* ([info (module-identifier-mapping-get the-table #'struct)]
               [type (cdr (assq (syntax->datum #'field) info))])
          (with-syntax ([type type])
            #'(quote type)))])))

(define-persistent-struct S ([x int] [y bool]))
(type-of-field S x) ;; => 'int

Ryan

> _________________________________________________
>  For list-related administrative tasks:
>  http://list.cs.brown.edu/mailman/listinfo/plt-scheme



Posted on the users mailing list.