[racket] help about a macro that uses a struct define with "make-struct-type"
Maurizio,
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:
> REPOSTED DUE TO COPY/PASTE ERRORS IN MY ORIGINAL MAIL.
> ------------------------------------------------------
>
> 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
>
>