[plt-scheme] super-structs and structure type descriptors

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Thu Jun 2 08:07:11 EDT 2005

Technically what you want are assertions not contracts. -- Matthias


On Jun 1, 2005, at 11:12 PM, Arjun Guha wrote:

>   For list-related administrative tasks:
>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme
>
> Hi,
>
> I'm writing a macro called `define-type/struct' that, as the name 
> suggests,
> allows you to attach
> contracts to fields in the definition.  I want contracts on a 
> structure's
> fields within a module, but I
> cannot export the structure (so I can't use provide/contract on the 
> struct).
>
> I believe I can do structures without super-structures, but I'm having 
> trouble
> getting derived structures
> to work.  Specifically, I can't figure out what I need to send as the
> super-struct-type to make-struct-
> type.  Here's a snippit of code from the macro:
>
> ---Code---
>
>   (define-syntax (define-struct/contract stx)
>     (syntax-case stx ()
>       [(_ (name super-struct) ([field type] ...))
>        (let* ([fields (syntax->list #'(field ...))]
>               [names (build-struct-names #'name fields #f #f #'name)]
>               [field-count (length fields)])
>          (let-values ([(struct-desc make-struct struct? struct-get
> struct-set!)
>                        (make-struct-type (syntax-object->datum #'name)
>                                          #f ; INCORRECT
>                                          field-count 0)])
>            #`(begin
>                ; Defines structure type descriptor.
>                (define #,(first names) #,struct-desc) ; and so on ...
>
> ---End code---
>
> What goes where I have `#f ;INCORRECT' in my code?  If that snippet 
> isn't
> enough, here is all the code I
> have so far:
>
> ---Code---
>
>   (require-for-syntax (lib "struct.ss" "syntax")) ; build-struct-names
>   (require-for-syntax (lib "contract.ss" "mzlib")) ; the usual
>   (require-for-syntax (lib "list.ss" "mzlib")) ; the usual
>   (require (lib "contract.ss" "mzlib"))
>
>   (provide define-struct/contract)
>
>   (define-syntax (define-struct/contract stx)
>     (syntax-case stx ()
>       [(_ (name super-struct) ([field type] ...))
>        (let* ([fields (syntax->list #'(field ...))]
>               [names (build-struct-names #'name fields #f #f #'name)]
>               [types (syntax->list #'(type ...))]
>               [super-struct-info (syntax-local-value #'super-struct)]
>               [field-count (length fields)])
>          (display super-struct-info)
>          (let-values ([(struct-desc make-struct struct? struct-get
> struct-set!)
>                        (make-struct-type (syntax-object->datum #'name)
>                                          #f ; INCORRECT
>                                          ;(syntax-object->datum (first
> super-struct-info))
>                                          field-count 0)])
>            #`(begin
>                ; Defines structure type descriptor.
>                (define #,(first names) #,struct-desc)
>
>                ; Defines the predicate/type.
>                (define #,(third names) #,struct?)
>
>                ; Generates the constructor.
>                (define/contract #,(second names)
>                  (#, at types . -> . #,struct?)
>                  #,make-struct)
>
>                ; Generates accessors.
>                #,@(let loop ([n 0])
>                     (if (= n field-count)
>                         empty
>                         (cons #`(define/contract
>                                   #,(list-ref names (+ 3 n))
>                                   (#,struct? . -> . #,(list-ref types 
> n))
>                                   (lambda (s) (#,struct-get s #,n)))
>                               (loop (+ n 1)))))
>
>                ; For completeness, I grudgingly provide mutators.  DO 
> NOT USE!
>                #,@(let loop ([n 0])
>                     (if (= n field-count)
>                         empty
>                         (cons #`(define/contract
>                                   #,(list-ref names (+ 3 field-count 
> n))
>                                   (#,struct? #,(list-ref types n) . -> 
> . any)
>                                   (lambda (s v) (#,struct-get s #,n)))
>                               (loop (+ n 1)))))
>
>                ; Funky thing
>                (define-syntax name
>                  (list-immutable (quote-syntax #,(first names))
>                                  (quote-syntax #,(second names))
>                                  (quote-syntax #,(third names))
>                                  (list-immutable) ; FIXME!
>                                  (list-immutable) ; FIXME!
>                                  #,(or #'super-struct #t)))
>
>                )))]))
>
> ---End code---
>
> Thanks.
>
> -Arjun
>
>



Posted on the users mailing list.