[racket] Can impersonator be a cache?
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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20140815/2ebf27c7/attachment-0001.html>