[racket] Can impersonator be a cache?

From: Roman Klochkov (kalimehtar at mail.ru)
Date: Sat Aug 16 05:40:06 EDT 2014

 I think, yes. Thank you!


Fri, 15 Aug 2014 21:26:55 -0400 от "Alexander D. Knauth" <alexander at knauth.org>:
>If what you want is lazy struct, would something like this work?
>
>#lang racket/base
>
>(require racket/splicing
>         racket/promise
>         (for-syntax racket/base
>                     racket/struct-info
>                     syntax/parse
>                     racket/syntax))
>
>(module+ test
>  (require rackunit)
>  (lazy-struct object (a b c))
>  (define obj (object #:loader (λ (field)
>                                 (printf "calculating ~a\n" field)
>                                 field)))
>  (let ([out (open-output-string)])
>    (parameterize ([current-output-port out])
>      (check-equal? (get-output-string out) "")
>      (check-equal? (object-a obj) 'a)
>      (check-equal? (get-output-string out) "calculating a\n")
>      (check-equal? (object-a obj) 'a)
>      (check-equal? (get-output-string out) "calculating a\n")
>      (check-match obj (object 'a 'b 'c))
>      (check-equal? (get-output-string out) "calculating a\ncalculating b\ncalculating c\n")
>      (close-output-port out)
>      ))
>  )
>
>(define-syntax lazy-struct
>  (lambda (stx)
>    (syntax-parse stx
>      [(lazy-struct name:id (field:id ...) . options)
>       #:with (~var struct:name) (format-id #'name "struct:~a" #'name #:source #'name)
>       #:with name? (format-id #'name "~a?" #'name #:source #'name)
>       #:with (name-field ...) (for/list ([field-id (in-list (syntax->list #'(field ...)))])
>                                 (format-id #'name "~a-~a" #'name field-id #:source #'name))
>       #:with (old-name-field ...) (generate-temporaries #'(name-field ...))
>       #'(splicing-local [(splicing-local [(struct name (field ...) . options)]
>                            (define old-name name)
>                            (define old-struct:name struct:name)
>                            (define old-name? name?)
>                            (define old-name-field name-field)
>                            ...
>                            (define (make-name #:loader loader)
>                              (old-name (delay (loader 'field)) ...)))]
>           (define name? old-name?)
>           (define struct:name old-struct:name)
>           (define (name-field name)
>             (force (old-name-field name)))
>           ...
>           (define-syntax name
>             (make-struct-desc #:descriptor #'struct:name
>                               #:constructor #'make-name
>                               #:predicate #'name?
>                               #:accessors (reverse (list #'name-field ...))
>                               #:mutators (list (begin 'name-field #f) ...)
>                               #:super #t)))])))
>
>(begin-for-syntax
>  (define (make-struct-desc #:descriptor [descriptor-id #f]
>                            #:constructor constructor-id
>                            #:predicate [predicate-id #f]
>                            #:accessors [accessors '(#f)]
>                            #:mutators [mutators (map (λ (x) #f) accessors)]
>                            #:super [super #f])
>    (with-syntax ([constructor constructor-id])
>      (proc+struct-info
>       (lambda (stx)
>         (syntax-parse stx
>           [(name . stuff)
>            (quasisyntax/loc stx
>              (#,(syntax/loc #'name constructor) . stuff))]
>           [name (syntax/loc stx constructor)]))
>       (list descriptor-id constructor-id predicate-id accessors mutators super))))
>  (struct proc+struct-info (proc struct-info) #:transparent
>    #:property prop:procedure (struct-field-index proc)
>    #:property prop:struct-info (λ (this) (proc+struct-info-struct-info this)))
>  )
>
>
>On Aug 15, 2014, at 2:16 PM, Roman Klochkov < kalimehtar at mail.ru > wrote:
>>I want to have lazy-load struct. In C++ it is called proxy reference (when dereferencing return new (or cached) object loaded on demand)
>>
>>Ideally, it would be like
>>(lazy-struct obj (a b c) #:loader load-data)
>>
>>then
>>
>>(define my-obj (make-ref obj "unique-id"))
>>
>>(displayln (obj-a my-obj)) ;; here content of my-obj should be loaded via load-data.
>>
>>And match pattern would also work.
>>
>>Now I made API with (get-field my-obj 'a), but is not Racketish.
>>
>>Fri, 15 Aug 2014 08:45:59 -0400 от "Alexander D. Knauth" < alexander at knauth.org >:
>>>
>>>Why not just define a new version of object-a that does that?
>>>You probably have a good reason, but what is it?  
>>>Is it to change the result of struct->vector, allow (object a b c) as a match pattern to match ref, or what?  
>>>
>>>On Aug 15, 2014, at 6:42 AM, Roman Klochkov < kalimehtar at mail.ru > wrote:
>>>
>>>> I have
>>>> (struct object (a b c))
>>>> (struct reference (id data))
>>>>  
>>>> Let `ref' -- an instance of `reference'.
>>>>  
>>>> I want, that (object-a ref) call my own (ref-get object-a ref)
>>>>  
>>>> (define (ref-get accessor ref)
>>>> (unless (weak-box-value (ref-data ref))
>>>> (set-ref-data! ref (make-weak-box (load-data (ref-id ref)))))
>>>> (accessor (weak-box-value (ref-data ref))))
>>>>  
>>>> Is it possible?  
>>>> I found `impersonate-struct', but it is not struct itself (no `id' field).  
>>>> I can add `prop:impersonator-of',. but how to redirect accessors?
>>>>  
>>>> --  
>>>> Roman Klochkov
>>>> ____________________
>>>> Racket Users list:
>>>>   http://lists.racket-lang.org/users
>>>
>>
>>
>>--  
>>Roman Klochkov


-- 
Roman Klochkov
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20140816/a722b440/attachment-0001.html>

Posted on the users mailing list.