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

From: Sam Tobin-Hochstadt (samth at cs.indiana.edu)
Date: Mon Jan 20 18:53:42 EST 2014

On Mon, Jan 20, 2014 at 6:49 PM, Scott Klarenbach <scott at pointyhat.ca> wrote:
>> 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.
>
>
> Good point, Sam made it at the same time.  :)
>
> Wouldn't a syntax-time hash-table introduce problems as well since there's
> no guarantee it gets copied over either?

There are techniques for managing syntax-time state such as hash
tables to make this work better [1], but as you say, this is trickier.
 That's why when it's possible, it's basically always better to go
with binding information.  That's why `struct` works the way it does.

[1] See the papers "You want it when" by Matthew, or "Languages as
Libraries" by a bunch of us for more on these techniques.

Sam

>
>
>
> On Mon, Jan 20, 2014 at 3:35 PM, Carl Eastlund <carl.eastlund at gmail.com>
> wrote:
>>
>> 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
>>>
>>
>
>
>
> --
> 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
>

Posted on the users mailing list.