[racket] using macros and new structs with make-struct-type

From: Maurizio Giordano (maurizio.giorda at gmail.com)
Date: Thu Jul 28 10:30:57 EDT 2011

Hi all,

I am not a racket expert, so my problem could be
simpy due to my few knwoledge about macros.

My problem is when I am using macros and 
user-defined structs.

I have defined my new structure with "make-struct-type":

  ; Multiset datatype definition
  (define-values (s:mset make-mset mset? mset-ref mset-set!)
     (make-struct-type 'mset #f 1 0 #f
                 (list (cons prop:custom-write mset-print))))

I have defined a new reader and writer for this new datatype.
Here you find an example of use of the "mset" datatype.

> (define d1 (make-mset #(1 2 3 4)))
> d1
<1,2,3,4>      ; printed (and read) as a comma-separated set of elements
encolsed by <>
> (mset? d1)   ; the datatype checker
#t

Now I have the following macro:

 (define-syntax (mm stx)Hi all,

I am not a racket expert, so my problem could be
simpy due to my few knwoledge about macros.

My problem is when I am using macros and 
user-defined structs.

I have defined my new structure with "make-struct-type":

  ; Multiset datatype definition
  (define-values (s:mset make-mset mset? mset-ref mset-set!)
     (make-struct-type 'mset #f 1 0 #f
                 (list (cons prop:custom-write mset-print))))

I have defined a new reader and writer for this new datatype.
Here you find an example of use of the "mset" datatype.

> (define d1 (make-mset #(1 2 3 4)))
> d1
<1,2,3,4>      ; printed (and read) as a comma-separated set of elements
encolsed by <>
> (mset? d1)   ; the datatype checker
#t

Now I have the following macro:

 (define-syntax (mm stx)
   (syntax-case stx ()                
        [(_ input ...)
         (let* ((l1 (syntax '(input ...)))
                (l2 '(input ...)))
           (map (lambda (x) (print-type x)) l2)   ; assume print-type is
imported for syntax
           (datum->syntax stx `(map (lambda (x) (print-type x)) ,l1)
stx))]))   ; I need this quasiquote/unquote

Where "print-type" is a trivial function that checks the type of "x"
and prints it:

 (define (print-type x) 
   (cond ((symbol? x) (printf "SYM: ~s\n" x))
          ((integer? x) (printf "INT: ~s\n" x))
          ((list? x) (printf "LIST: ~s\n" x))
          ((mset? x) (printf "MSET: ~s\n" x))
         (else (printf "UNK: ~s\n" x))) 
   x)

I get the following printout when I call the macro like this:

> (mm 1 x (1 y) < 1, z >)
INT: 1
SYM: x
LIST: (1 y)
UNK: <1, z>
...
INT: 1
SYM: x
LIST: (1 y)
MSET: <1, z>

It seems that when binding "l2" in the let, the "mset" datatype
information
is lost, while "l1" in the macro template contains all information.

>From the documentation of "syntax->datum" I have read the following: 
"Returns a datum by stripping the lexical information, source-location
information, properties, and certificates from stx. Inside of pairs,
(immutable) vectors, (immutable) boxes, immutable hash table values (not
keys), and immutable prefab structures, syntax objects are recursively
stripped."

My structure is not a prefab ... Is this the problem?
How can I preserve the "mset" information in the let binding?

I will appreciate any help.

Thank You.

Maurizio. 
   (syntax-case stx ()                
        [(_ input ...)
         (let* ((l1 (syntax '(input ...)))
                (l2 '(input ...)))
           (map (lambda (x) (print-type x)) l2)   ; assume print-type is
imported for syntax
           (datum->syntax stx `(map (lambda (x) (print-type x)) ,l1)
stx))]))   ; I need this quasiquote/unquote

Where "print-type" is a trivial function that checks the type of "x"
and prints it:

 (define (print-type x) 
   (cond ((symbol? x) (printf "SYM: ~s\n" x))
          ((integer? x) (printf "INT: ~s\n" x))
          ((list? x) (printf "LIST: ~s\n" x))
          ((mset? x) (printf "MSET: ~s\n" x))
         (else (printf "UNK: ~s\n" x))) 
   x)

I get the following printout when I call the macro like this:

> (mm 1 x (1 y) < 1, z >)
INT: 1
SYM: x
LIST: (1 y)
UNK: <1, z>
...
INT: 1
SYM: x
LIST: (1 y)
MSET: <1, z>

It seems that when binding "l2" in the let, the "mset" datatype
information
is lost, while "l1" in the macro template contains all information.

>From the documentation of "syntax->datum" I have read the following: 
"Returns a datum by stripping the lexical information, source-location
information, properties, and certificates from stx. Inside of pairs,
(immutable) vectors, (immutable) boxes, immutable hash table values (not
keys), and immutable prefab structures, syntax objects are recursively
stripped."

My structure is not a prefab ... Is this the problem?
How can I preserve the "mset" information in the let binding?

I will appreciate any help.

Thank You.

Maurizio. 



Posted on the users mailing list.