If you get a good solution, please let the rest of us know. For the new simulation collection, I need to be able to maintain statistics and history for selected 'variables'. I currently do this with a struct and a prop:procedure to implement a getter and setter. This requires using the struct instance as a procedure - i.e., it is parenthesized like a parameter. This works and I can use it in any context. But, it would be nice to have a mechanism that provided the same capability without the procedure syntax that worked in all contexts.
Doug On Wed, Nov 20, 2013 at 10:35 AM, Emina Torlak <[email protected]>wrote: > I believe Robby's solution will work. It's basically similar to what I > had in mind, but I was hoping I'd be able to avoid it :) > > The crux of the issue is the need for unique identifiers for variable > locations. I also track updates to vectors and structs, for example, and > this is easy precisely because I can use their identities to compute the > "location" of the update. So, boxing values in "raw" variables will have > the same effect. > > In terms of implementation, though, it'll be trickier. As far as I can > tell, this approach involves whole-module analysis and transformation: > > * Expand the module completely. > * Find all uses of set! and collect their targets. > * Rewrite the def and all uses of target variables to perform auto boxing > and unboxing. > > If there are tricks/constructs that I should use for the above steps, I'd > love to hear them. Or, of course, if there is some way to obtain variable > location identifiers from the runtime, that would be great to know as well. > > Emina > > > > > > On Wed, Nov 20, 2013 at 5:19 AM, Robby Findler < > [email protected]> wrote: > >> I didn't try it, but you it might work to use local-expand and then find >> all the binding forms and then rewrite them to use boxes (or some other >> source of uniqueness you might have around). >> >> Robby >> >> >> On Wed, Nov 20, 2013 at 12:53 AM, Emina Torlak >> <[email protected]>wrote: >> >>> This is how my solution currently works, but unfortunately, it's not >>> quite right. Here is a small example that demonstrates why, assuming the >>> implementation based on free-id-table: >>> >>> (define (cell init) >>> (let ([x init]) >>> (case-lambda >>> [() x] >>> [(v) (set! x v)]))) >>> >>> (define foo (cell 0)) >>> (define bar (cell 1)) >>> >>> > (foo 2) >>> > (bar 3) >>> > (foo) >>> 2 >>> > (bar) >>> 3 >>> > (dict->list global) >>> '((.#<syntax:18:17 x> . 3)) >>> >>> In the above scenario, I need the global map to contain two bindings: >>> one for the location of 'foo.x' and the other for the location of 'bar.x.' >>> >>> >>> Emina >>> >>> >>> >>> On Tue, Nov 19, 2013 at 10:31 PM, Sam Tobin-Hochstadt < >>> [email protected]> wrote: >>> >>>> I think that just identifiers and `free-id-table`s should work here. >>>> Here's your example: >>>> >>>> #lang racket >>>> >>>> (require syntax/id-table (only-in racket [set! #%set!])) >>>> >>>> (define global (make-free-id-table)) >>>> >>>> (define-syntax-rule (location-of id) #'id) >>>> >>>> (define-syntax-rule (set! id expr) >>>> (let ([v expr]) >>>> (dict-set! global (location-of id) v) >>>> (#%set! id v))) >>>> >>>> > (define x 1) >>>> > (set! x 2) >>>> > (set! x 3) >>>> > (for/list ([(k v) (in-dict global)]) (list k v)) >>>> '((.#<syntax:4:8 x> 3)) >>>> >>>> Also at https://gist.github.com/samth/7558673 >>>> >>>> Sam >>>> >>>> On Mon, Nov 18, 2013 at 2:43 PM, Emina Torlak <[email protected]> >>>> wrote: >>>> > I'm using Racket to implement a language for which I need to track >>>> state >>>> > updates---in particular, variable mutation using set!. For example, >>>> > consider this module definition: >>>> > >>>> > #lang racket >>>> > >>>> > (require (only-in racket [set! #%set!])) >>>> > >>>> > (define global (make-hash)) >>>> > >>>> > (define-syntax-rule (location-of id) >>>> > (#%variable-reference id)) ; doesn't quite do the right thing >>>> > >>>> > (define-syntax-rule (set! id expr) >>>> > (let ([val expr]) >>>> > (hash-set! global (location-of id) val) >>>> > (#%set! id val))) >>>> > >>>> > When I evaluate the following sequence of forms against the above >>>> > definition, I would like the global hash map to contain just one >>>> binding >>>> > that maps the location for 'x' to the value 2. With the above >>>> > implementation I get two map entries, since variable-reference >>>> doesn't quite >>>> > do what I hoped it did: >>>> > >>>> >> (define x 0) >>>> >> (set! x 1) >>>> >> (set! x 2) >>>> >> x >>>> > 2 >>>> >> global >>>> > '#hash((#<variable-reference> . 1) (#<variable-reference> . 2)) >>>> > >>>> > Is there another construct in Racket that I could use for this >>>> purpose? If >>>> > not, can something like this be implemented and how much work would it >>>> > entail? >>>> > >>>> > I have a purely macro-based solution that works for the most part, >>>> but it's >>>> > fragile and there are corner cases for which it is just wrong. So, >>>> before >>>> > trying to fix that, I was wondering if there is a nicer way to solve >>>> it by >>>> > somehow getting handles for variable locations that are comparable >>>> using eq? >>>> > or equal? >>>> > >>>> > Thanks! >>>> > >>>> > Emina >>>> > >>>> > >>>> > ____________________ >>>> > Racket Users list: >>>> > http://lists.racket-lang.org/users >>>> > >>>> >>> >>> >>> ____________________ >>> Racket Users list: >>> http://lists.racket-lang.org/users >>> >>> >> > > ____________________ > Racket Users list: > http://lists.racket-lang.org/users > >
____________________ Racket Users list: http://lists.racket-lang.org/users

