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

From: Carl Eastlund (carl.eastlund at gmail.com)
Date: Mon Jan 20 18:35:48 EST 2014

But there's no guarantee that if someone imports the original name
somewhere, renames it somehow, etc., that they'll copy over a <name>-META
binding as well.  Using a binding that carries everything with it, or using
a syntax-time hash table that carries out of band data that can be looked
up based on the original binding, is reliable.  Using an extra binding that
_should_ be there in most namespaces, can be broken by contexts you have no
control over.

Carl Eastlund


On Mon, Jan 20, 2014 at 6:31 PM, Scott Klarenbach <scott at pointyhat.ca>wrote:

> 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
>
> ____________________
>   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/5c93f145/attachment-0001.html>

Posted on the users mailing list.