[racket] Structs and syntax-local-value ... how is the struct name overloaded? (Greg Hendershott)

From: Scott Klarenbach (scott at pointyhat.ca)
Date: Mon Jan 20 18:31:43 EST 2014

>
> If/when it does matter, instead you could use a hashtable on the side,
> mapping from the procedure to the info. Of course that way, you need
> to use `(lookup thing)` to get the info.


Not to mention that it's vastly simpler to do it this way.  You get a
straightforward transformer proc and a hashtable bound as syntax.

This is partly a learning exercise for me - so it's valuable to go through
- but the more I look at it the more I think it's a lot of complexity just
to be able to overload the struct name, when it would suffice for match and
other macros that wanted compile-time meta info to follow a convention like
struct-name-META or something.  Afterall, structs already come with a lot
of magical bindings that you have to learn by convention, what's one more?

Just my two cents.

sk


On Mon, Jan 20, 2014 at 1:41 PM, <users-request at racket-lang.org> wrote:

> Send users mailing list submissions to
>         users at racket-lang.org
>
> To subscribe or unsubscribe via the World Wide Web, visit
>         http://lists.racket-lang.org/users/listinfo
> or, via email, send a message with subject or body 'help' to
>         users-request at racket-lang.org
>
> You can reach the person managing the list at
>         users-owner at racket-lang.org
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of users digest..."
>
>
> [Racket Users list:
>  http://lists.racket-lang.org/users ]
>
>
> Today's Topics:
>
>    1. Re: Structs and syntax-local-value ... how is the struct name
>       overloaded? (Carl Eastlund)
>    2. Re: Structs and syntax-local-value ... how is the struct name
>       overloaded? (Greg Hendershott)
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Mon, 20 Jan 2014 13:00:35 -0500
> From: Carl Eastlund <carl.eastlund at gmail.com>
> To: "Alexander D. Knauth" <alexander at knauth.org>
> Cc: Scott Klarenbach <scott at pointyhat.ca>, Racket mailing list
>         <users at racket-lang.org>
> Subject: Re: [racket] Structs and syntax-local-value ... how is the
>         struct name overloaded?
> Message-ID:
>         <CAEOPtY09_5EUFpOn6uYBcJAB+TXTdDk=EK-DUHbLU2wu=
> XzDZw at mail.gmail.com>
> Content-Type: text/plain; charset="utf-8"
>
> Yes, that's exactly it.
>
> Carl Eastlund
>
>
> On Mon, Jan 20, 2014 at 10:13 AM, Alexander D. Knauth
> <alexander at knauth.org>wrote:
>
> > I'm just curious, is this what you mean?
> >
> > #lang racket
> >
> > (require rackunit
> >          (for-syntax
> >           syntax/parse))
> >
> > (begin-for-syntax
> >   (struct proc-with-info (proc info) #:property prop:procedure
> > (struct-field-index proc)))
> >
> > (define-syntax thing
> >   (proc-with-info (lambda (stx)
> >                     (syntax-parse stx #:literals (thing)
> >                                   [(thing x ...)
> >                                    #'(#%app thing x ...)]
> >                                   [thing
> >                                    #'(lambda (x) x)]))
> >                   'info))
> >
> > (define-syntax get-info
> >   (lambda (stx)
> >     (syntax-parse stx
> >                   [(get-info x)
> >                    (datum->syntax stx `(quote ,(proc-with-info-info
> > (syntax-local-value #'x))))])))
> >
> > (check-equal? (thing 1) 1)
> > (let ([x (random)])
> >   (check-equal? (thing x) x))
> >
> > (check-equal? (get-info thing)
> >               'info)
> >
> >
> > On Jan 20, 2014, at 12:37 AM, Carl Eastlund wrote:
> >
> > It sounds like you've got it.  A syntax transformer must be a procedure,
> > and prop:procedure is how you make a procedure that can also be something
> > else.  So if you want something to be both a syntax transformer and a
> > struct binding, for instance, you need to use prop:procedure and
> > prop:struct-info.  You can't make something both a procedure and a
> symbol,
> > because symbols don't work via struct properties, but you could make it
> > both a procedure and a struct that contains a symbol.
> >
> > Carl Eastlund
> >
> > On Mon, Jan 20, 2014 at 12:21 AM, Scott Klarenbach <scott at pointyhat.ca
> >wrote:
> >
> >>  That doesn't look like a complete program; what does #'done refer to?
> >>> And where did the "val is: " printout go?
> >>
> >>
> >> That's just a quick hack for illustration purposes.  #''done is just
> >> something to return. (note the two quotes)  The output is:
> >> val is: #<procedure:self-ctor-checked-struct-info>#<procedure:posn>
> >> 'done
> >>
> >> But your supposition is correct: posn is always bound as syntax to a
> >>> self-ctor-checked-struct-info-object.  That object works as a syntax
> >>> transformer; run time references to posn are transformed into
> references to
> >>> the actual procedure value you're seeing as #<procedure:posn>.
> >>
> >>
> >> Thanks Carl, it's starting to make sense.  So the prop:procedure of the
> >> struct is actually the transformer?  And so in expression context it
> acts
> >> as a macro, but in syntax-local-value context it acts as a struct?  I
> was
> >> trying to produce something similar, but ran into the following issues:
> >>
> >> Say I want (define-syntax (posn) ...) to transform syntax, but I also
> >> want (syntax-local-value #'posn) to return 'something.
> >> Without the struct trick I can only have one but not the other.  I could
> >> either have (define-syntax posn 'something), and lose the ability to
> call
> >> it as a macro (illegal syntax), or have (define-syntax (posn)
> #'something),
> >> and then (syntax-local-value #'posn) returns the transformer, rather
> than
> >> 'something.
> >>
> >>
> >>
> >>
> >>
> >> On Sun, Jan 19, 2014 at 8:57 PM, Scott Klarenbach <scott at pointyhat.ca
> >wrote:
> >>
> >>> It's not changing it, I'm just trying to figure out the implementation
> >>> and understand what I'm seeing.
> >>> For example, given this:
> >>>
> >>> (struct posn (x y))
> >>>
> >>> (define-syntax (test stx)
> >>>   (syntax-case stx ()
> >>> [(_ x)
> >>>  (printf "val is: ~s" (syntax-local-value #'posn))
> >>>  #''done]))
> >>>
> >>> > posn
> >>> #<procedure:posn>
> >>>
> >>> > (test x)
> >>> #<procedure:self-ctor-checked-struct-info>
> >>>
> >>> I'm surprised that the values are different.  Is posn actually always a
> >>> self-ctor-checked-struct-info object, but it's prop:procedure is
> defined to
> >>> allow for being used in an expression in the first case?
> >>>
> >>>
> >>>
> >>>
> >>> On Sun, Jan 19, 2014 at 8:40 PM, Carl Eastlund <
> carl.eastlund at gmail.com>wrote:
> >>>
> >>>> If syntax-local-value is returning something other than the value you
> >>>> put in, that's a bug.  It shouldn't be wrapping it or changing it in
> any
> >>>> way.  Do you have a program where you bind something via
> define-syntax that
> >>>> satisfies struct-info?, and get something out via syntax-local-value
> that
> >>>> doesn't?
> >>>>
> >>>> Carl Eastlund
> >>>>
> >>>> On Sun, Jan 19, 2014 at 11:27 PM, Scott Klarenbach <
> scott at pointyhat.ca>wrote:
> >>>>
> >>>>> But I don't see how the same binding can be a transformer and also
> >>>>> return something else (like a list, or a checked-struct-info-thing)
> via
> >>>>> syntax-local-value.
> >>>>>
> >>>>> If I bind my-fn as a transformer, then any other macros that use it
> >>>>> with syntax-local-value will receive the transformer procedure back,
> not
> >>>>> any special meta data.  And if I bind it as meta data directly, ie
> >>>>> (define-syntax my-fn 'something) then it works with
> syntax-local-value but
> >>>>> any attempts to use it as a transformer result in illegal syntax.
> >>>>>
> >>>>> Even if I create a transformer that returns a struct which implements
> >>>>> both prop:procedure and prop:struct-info, using that binding with
> >>>>> syntax-local-value will return the transformer procedure itself,
> rather
> >>>>> than the final struct.
> >>>>>
> >>>>>
> >>>>>
> >>>>> On Sun, Jan 19, 2014 at 8:04 PM, Carl Eastlund <
> >>>>> carl.eastlund at gmail.com> wrote:
> >>>>>
> >>>>>> Yes, I believe that the name of a structure defined by "struct" is
> >>>>>> bound at syntax-time to a value that implements both
> prop:procedure, so
> >>>>>> that it can expand to a use of the constructor when used in an
> expression,
> >>>>>> and prop:struct-info so that it can be use to look up static
> information
> >>>>>> when passed to relevant macros.
> >>>>>>
> >>>>>> Carl Eastlund
> >>>>>>
> >>>>>>
> >>>>>> On Sun, Jan 19, 2014 at 11:00 PM, Scott Klarenbach <
> >>>>>> scott at pointyhat.ca> wrote:
> >>>>>>
> >>>>>>> How is it that the definition of (struct my-name (x y)) can bind
> >>>>>>> *my-name* both as a #<procedure:my-name> at runtime and a
> >>>>>>> transformer-binding *my-name* that at compile time (via
> >>>>>>> syntax-local-value) produces
> #<procedure:self-ctor-checked-struct-info>.?
> >>>>>>>
> >>>>>>> Or, put another way, how can I define a transformer *my-fn* that
> >>>>>>> produces syntax, but that also exposes hidden meta-data under the
> same
> >>>>>>> binding to other macros that might wish to know about the binding
> at
> >>>>>>> compile time?
> >>>>>>>
> >>>>>>> I'm specifically wondering how the overloading works.  Is it some
> >>>>>>> clever use of prop:procedure?
> >>>>>>>
> >>>>>>> Thanks.
> >>>>>>>
> >>>>>>> --
> >>>>>>> Talk to you soon,
> >>>>>>>
> >>>>>>> Scott Klarenbach
> >>>>>>>
> >>>>>>> PointyHat Software Corp.
> >>>>>>> www.pointyhat.ca
> >>>>>>> p 604-568-4280
> >>>>>>> e scott at pointyhat.ca
> >>>>>>> 200-1575 W. Georgia
> >>>>>>> Vancouver, BC V6G2V3
> >>>>>>>
> >>>>>>> _______________________________________
> >>>>>>> To iterate is human; to recur, divine
> >>>>>>>
> >>>>>>> ____________________
> >>>>>>>   Racket Users list:
> >>>>>>>   http://lists.racket-lang.org/users
> >>>>>>>
> >>>>>>>
> >>>>>>
> >>>>>
> >>>>>
> >>>>> --
> >>>>> Talk to you soon,
> >>>>>
> >>>>> Scott Klarenbach
> >>>>>
> >>>>> PointyHat Software Corp.
> >>>>> www.pointyhat.ca
> >>>>> p 604-568-4280
> >>>>> e scott at pointyhat.ca
> >>>>> 200-1575 W. Georgia
> >>>>> Vancouver, BC V6G2V3
> >>>>>
> >>>>> _______________________________________
> >>>>> To iterate is human; to recur, divine
> >>>>>
> >>>>
> >>>>
> >>>
> >>>
> >>> --
> >>> Talk to you soon,
> >>>
> >>> Scott Klarenbach
> >>>
> >>> PointyHat Software Corp.
> >>> www.pointyhat.ca
> >>> p 604-568-4280
> >>> e scott at pointyhat.ca
> >>> 200-1575 W. Georgia
> >>> Vancouver, BC V6G2V3
> >>>
> >>> _______________________________________
> >>> To iterate is human; to recur, divine
> >>>
> >>
> >>
> >>
> >> --
> >> Talk to you soon,
> >>
> >> Scott Klarenbach
> >>
> >> PointyHat Software Corp.
> >> www.pointyhat.ca
> >> p 604-568-4280
> >> e scott at pointyhat.ca
> >> 200-1575 W. Georgia
> >> Vancouver, BC V6G2V3
> >>
> >> _______________________________________
> >> To iterate is human; to recur, divine
> >>
> >
> > ____________________
> >  Racket Users list:
> >  http://lists.racket-lang.org/users
> >
> >
> >
> -------------- next part --------------
> An HTML attachment was scrubbed...
> URL: <
> http://lists.racket-lang.org/users/archive/attachments/20140120/1cbff376/attachment-0001.html
> >
>
> ------------------------------
>
> Message: 2
> Date: Mon, 20 Jan 2014 16:40:56 -0500
> From: Greg Hendershott <greghendershott at gmail.com>
> To: users at racket-lang.org
> Subject: Re: [racket] Structs and syntax-local-value ... how is the
>         struct name overloaded?
> Message-ID:
>         <CAGspUn3DeoWR7Qfw=uPamDuV+6ig9asRt=-
> DcAjh+uViBbTYnA at mail.gmail.com>
> Content-Type: text/plain; charset=ISO-8859-1
>
> >> and prop:procedure is how you make a procedure that can also be
> something
> >> else.
>
> One thing to keep in mind is that there is _some_ overhead. In my
> recent experience, applying via prop:procedure took roughly 1.6X the
> time as applying a plain procedure. (This with the variant of
> prop:procedure where its value is an index to the field in the struct
> holding the procedure.)
>
> I don't know how much of the extra time is due to memory reference,
> missing the optimizer, and/or other?
>
> For many applications that doesn't matter, and it's worth it to have
> `thing` self-evaluate to the info.
>
> If/when it does matter, instead you could use a hashtable on the side,
> mapping from the procedure to the info. Of course that way, you need
> to use `(lookup thing)` to get the info.
>
>
> End of users Digest, Vol 101, Issue 60
> **************************************
>



-- 
Talk to you soon,

Scott Klarenbach

PointyHat Software Corp.
www.pointyhat.ca
p 604-568-4280
e scott at pointyhat.ca
200-1575 W. Georgia
Vancouver, BC V6G2V3

_______________________________________
To iterate is human; to recur, divine
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20140120/38038245/attachment-0001.html>

Posted on the users mailing list.