[racket] help about a macro that uses a struct define with "make-struct-type"

From: Carl Eastlund (cce at ccs.neu.edu)
Date: Fri Jul 29 11:09:52 EDT 2011


The problem here may be that macros are expanded at a separate phase
from the program's run-time.  Different phases have different stores,
and thus different versions of structure definitions.  Your custom
reader for the mset datatype produces an mset for use at run-time.
The run-time print-type detects this kind of mset, but the
compile-time print-type expects a different version of an mset.

Prefab structures would fix this part of the issue, because they do
not generate new types, they merely describe a subset of existing
types.  However, you cannot add a custom reader or writer property to
prefab types, so another part of your interface will break.

I do not know precisely what you need to detect this type at
compile-time for, so I don't have any advice on how to handle this for
your purposes.  I hope I have at least clarified the behavior you see.

Carl Eastlund

On Fri, Jul 29, 2011 at 8:35 AM, Maurizio Giordano
<maurizio.giorda at gmail.com> wrote:
> ------------------------------------------------------
> Hi all,
> I am not a racket expert, so my problem could be
> simply 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:
>  (require (for syntax multiset))   ;; import mset? for 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.
> PS. I read Tom McNulty last post "Advice on a macro for mutating
> structs...". Maybe my problem has some similarities with his...
> _________________________________________________
>  For list-related administrative tasks:
>  http://lists.racket-lang.org/listinfo/users

Posted on the users mailing list.