[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 12:20:33 EDT 2011

On Fri, Jul 29, 2011 at 12:05 PM, Maurizio Giordano
<maurizio.giorda at gmail.com> wrote:
> Hi Carl,
>
> On Fri, 2011-07-29 at 11:09 -0400, Carl Eastlund wrote:
>> 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.
> Ok. the difference between the two phases is now clear to me...
> what is not still clear is:
> 1) at compile-time the "mset?" checker function is known... otherwise I
> would see an "undefined mset?"
> (in fact I specify a (require (for-syntax multiset)), where multiset is
> a module implementing the new datastructure).
> 2) always at compile-time, the (mset? < ... >) expression returns #f.
> So it seems to me that at compile-time the struct object has lost some
> information.

There is one module called "multiset", but all of its definitions are
executed twice because your program uses them in two different phases:
once at run-time and once at compile-time.  That means
there are two different mset types with two different constructors and
two different mset? predicates.  Call the run-time versions mset.1 and
mset?.1, and the compile-time versions mset.2 and mset?.2.  Similarly,
you have print-type.1 and print-type.2 at run-time and compile-time.

Your custom reader produces an mset.1 value.  Your macro calls
print-type.2 which checks mset?.2, and mset?.2 produces #false when
given an mset.1 value.  The code your macro produces, however, calls
print-type.1, which checks mset?.1, and that produces #true (I'm using
the new long-form names of #f and #t for readability).  So no
information is being lost -- it's just that there are two versions of
everything running around, and they cannot be mixed and matched.

>> 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.
> Yes, you are right... I would like to keep my custom reader/writer.
> So I cannot use prefab structs.
>>
>> 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.
>
> At compile-time I would like to process the macro inputs (of course also
> <...> structs) to generate some pattern-matching "templates" to be
> injected in the code the macro generates and execute at runtime.
> Something like this:
>
> (define-syntax (mm stx)
>  (syntax-case stx ()
>     [(_ input ...)
>         (let* ((l1 (syntax '(input ...)))
>                (templates (... process/and/recognize msets in l1 ...)))
>           (datum->syntax stx
>                         `(lambda (x) ,(inject-code patterns)) stx))]))
>
> Therefore, what I really need is that the new data structure is parsed
> (and its type cecked) at compile time.
>
> Thanks,
> Cheers,
> Maurizio.

Are you sure you want to put mset values in as literal syntax?  That
leads to all sorts of odd behavior -- for instance, the contents of
those msets will need to be syntax at compile-time if they are to
contain expressions, but non-syntax at run-time if they are to contain
useful values.  The expansion system will not do this plumbing for
you.  You'll get a lot more "bang for your buck" if you instead just
use a match expander as both a pattern to recognize msets and a
constructor to build them.  This avoids all issues of crossing phase
boundaries, because the compile-time code acts entirely by recognizing
identifier bindings, and does not have to know about the
representation of msets at all.

--Carl



Posted on the users mailing list.