[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:49:02 EST 2014

>
> 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?



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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20140120/d9c0e7ff/attachment-0001.html>

Posted on the users mailing list.