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

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

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.html>

Posted on the users mailing list.