Merge pull request #179 from AlexKnauth/lens-join-struct
add lens-join/struct
This commit is contained in:
commit
c2c3b85d37
1
info.rkt
1
info.rkt
|
@ -14,6 +14,7 @@
|
||||||
"fancy-app"
|
"fancy-app"
|
||||||
"alexis-util"
|
"alexis-util"
|
||||||
"sweet-exp"
|
"sweet-exp"
|
||||||
|
"kw-make-struct"
|
||||||
"scribble-lib"))
|
"scribble-lib"))
|
||||||
|
|
||||||
|
|
||||||
|
|
21
lens/private/test-util/test-multi.rkt
Normal file
21
lens/private/test-util/test-multi.rkt
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#lang sweet-exp racket/base
|
||||||
|
|
||||||
|
provide test-multi*
|
||||||
|
|
||||||
|
require racket/match
|
||||||
|
racket/string
|
||||||
|
racket/format
|
||||||
|
syntax/parse/define
|
||||||
|
rackunit
|
||||||
|
for-syntax racket/base
|
||||||
|
syntax/parse
|
||||||
|
|
||||||
|
(define-simple-macro
|
||||||
|
(test-multi* ([test-id:id #:in [test-variant:expr ...]] ...)
|
||||||
|
body ...)
|
||||||
|
#:with [pair-id ...] (generate-temporaries #'[test-id ...])
|
||||||
|
#:with [which-test ...] (generate-temporaries #'[test-id ...])
|
||||||
|
(for* ([pair-id (in-list (list (cons 'test-variant test-variant) ...))] ...)
|
||||||
|
(match-define (cons which-test test-id) pair-id) ...
|
||||||
|
(test-case (string-join (list (format "~a = ~a" 'test-id which-test) ...) ", ")
|
||||||
|
body ...)))
|
|
@ -10,6 +10,7 @@
|
||||||
"string-split.rkt"
|
"string-split.rkt"
|
||||||
"match.rkt"
|
"match.rkt"
|
||||||
"set-filterer.rkt"
|
"set-filterer.rkt"
|
||||||
|
"struct-join.rkt"
|
||||||
)
|
)
|
||||||
|
|
||||||
(provide (all-from-out "syntax.rkt"
|
(provide (all-from-out "syntax.rkt"
|
||||||
|
@ -22,4 +23,5 @@
|
||||||
"string-split.rkt"
|
"string-split.rkt"
|
||||||
"match.rkt"
|
"match.rkt"
|
||||||
"set-filterer.rkt"
|
"set-filterer.rkt"
|
||||||
|
"struct-join.rkt"
|
||||||
))
|
))
|
||||||
|
|
|
@ -19,3 +19,4 @@ this library being backwards-compatible.
|
||||||
@include-section["string-split.scrbl"]
|
@include-section["string-split.scrbl"]
|
||||||
@include-section["match.scrbl"]
|
@include-section["match.scrbl"]
|
||||||
@include-section["set-filterer.scrbl"]
|
@include-section["set-filterer.scrbl"]
|
||||||
|
@include-section["struct-join.scrbl"]
|
||||||
|
|
81
unstable/lens/struct-join.rkt
Normal file
81
unstable/lens/struct-join.rkt
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
#lang sweet-exp racket/base
|
||||||
|
|
||||||
|
provide lens-join/struct
|
||||||
|
|
||||||
|
require racket/local
|
||||||
|
racket/match
|
||||||
|
lens/private/base/main
|
||||||
|
kw-make-struct
|
||||||
|
for-syntax racket/base
|
||||||
|
syntax/parse
|
||||||
|
module+ test
|
||||||
|
require rackunit lens/private/hash/main lens/private/test-util/test-multi
|
||||||
|
|
||||||
|
(begin-for-syntax
|
||||||
|
(define-splicing-syntax-class field-lenses
|
||||||
|
#:attributes ([lens-expr 1] [lens-id 1] [vw-id 1] [norm 1])
|
||||||
|
[pattern (~seq lens-expr:expr ...)
|
||||||
|
#:with [lens-id ...] (generate-temporaries #'[lens-expr ...])
|
||||||
|
#:with [vw-id ...] (generate-temporaries #'[lens-expr ...])
|
||||||
|
#:with [norm ...] #'[vw-id ...]]
|
||||||
|
[pattern (~seq fst-lens:expr ...+ rst:field-lenses)
|
||||||
|
#:with [fst-lens-id ...] (generate-temporaries #'[fst-lens ...])
|
||||||
|
#:with [fst-vw-id ...] (generate-temporaries #'[fst-lens ...])
|
||||||
|
#:with [lens-expr ...] #'[fst-lens ... rst.lens-expr ...]
|
||||||
|
#:with [lens-id ...] #'[fst-lens-id ... rst.lens-id ...]
|
||||||
|
#:with [vw-id ...] #'[fst-vw-id ... rst.vw-id ...]
|
||||||
|
#:with [norm ...] #'[fst-vw-id ... rst.norm ...]]
|
||||||
|
[pattern (~seq (~seq kw:keyword fst-lens:expr) ...+ rst:field-lenses)
|
||||||
|
#:with [fst-lens-id ...] (generate-temporaries #'[fst-lens ...])
|
||||||
|
#:with [fst-vw-id ...] (generate-temporaries #'[fst-lens ...])
|
||||||
|
#:with [lens-expr ...] #'[fst-lens ... rst.lens-expr ...]
|
||||||
|
#:with [lens-id ...] #'[fst-lens-id ... rst.lens-id ...]
|
||||||
|
#:with [vw-id ...] #'[fst-vw-id ... rst.vw-id ...]
|
||||||
|
#:with [[fst-kw/vw-id ...] ...] #'[[kw fst-vw-id] ...]
|
||||||
|
#:with [norm ...] #'[fst-kw/vw-id ... ... rst.norm ...]]
|
||||||
|
))
|
||||||
|
|
||||||
|
(define-syntax lens-join/struct
|
||||||
|
(lambda (stx)
|
||||||
|
(syntax-parse stx
|
||||||
|
[(lens-join/struct s:id flds:field-lenses)
|
||||||
|
#:with make/kw-form #`(make/kw/derived #,stx s flds.norm ...)
|
||||||
|
#:with [[lens-id/vw-id ...] ...] #'[[flds.lens-id flds.vw-id] ...]
|
||||||
|
#`(local [(define flds.lens-id flds.lens-expr) ...]
|
||||||
|
(make-lens
|
||||||
|
(λ (tgt)
|
||||||
|
(define flds.vw-id (lens-view flds.lens-id tgt))
|
||||||
|
...
|
||||||
|
make/kw-form)
|
||||||
|
(λ (tgt nvw)
|
||||||
|
(match-define make/kw-form nvw)
|
||||||
|
(lens-set/list tgt lens-id/vw-id ... ...))))])))
|
||||||
|
|
||||||
|
(module+ test
|
||||||
|
(struct foo (a b c) #:transparent)
|
||||||
|
(define foo-hash-lens1
|
||||||
|
(lens-join/struct foo
|
||||||
|
(hash-ref-lens 'a)
|
||||||
|
(hash-ref-lens 'b)
|
||||||
|
(hash-ref-lens 'c)))
|
||||||
|
(define foo-hash-lens2
|
||||||
|
(lens-join/struct foo
|
||||||
|
#:a (hash-ref-lens 'a)
|
||||||
|
#:b (hash-ref-lens 'b)
|
||||||
|
#:c (hash-ref-lens 'c)))
|
||||||
|
(define foo-hash-lens3
|
||||||
|
(lens-join/struct foo
|
||||||
|
#:c (hash-ref-lens 'c)
|
||||||
|
#:a (hash-ref-lens 'a)
|
||||||
|
#:b (hash-ref-lens 'b)))
|
||||||
|
(define foo-hash-lens4
|
||||||
|
(lens-join/struct foo
|
||||||
|
(hash-ref-lens 'a)
|
||||||
|
#:c (hash-ref-lens 'c)
|
||||||
|
#:b (hash-ref-lens 'b)))
|
||||||
|
(test-multi* ([foo-hash-lens #:in [foo-hash-lens1 foo-hash-lens2 foo-hash-lens3 foo-hash-lens4]])
|
||||||
|
(check-equal? (lens-view foo-hash-lens (hash 'a 1 'b 2 'c 3))
|
||||||
|
(foo 1 2 3))
|
||||||
|
(check-equal? (lens-set foo-hash-lens (hash 'a 1 'b 2 'c 3) (foo 10 20 30))
|
||||||
|
(hash 'a 10 'b 20 'c 30))
|
||||||
|
))
|
30
unstable/lens/struct-join.scrbl
Normal file
30
unstable/lens/struct-join.scrbl
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#lang scribble/manual
|
||||||
|
|
||||||
|
@(require lens/private/doc-util/main)
|
||||||
|
|
||||||
|
@title{Joining lenses with structs}
|
||||||
|
|
||||||
|
@defmodule[unstable/lens/struct-join]
|
||||||
|
|
||||||
|
@defform[(lens-join/struct struct-id field-lens ...)
|
||||||
|
#:grammar ([field-lens (code:line lens-expr)
|
||||||
|
(code:line field-keyword lens-expr)])]{
|
||||||
|
Like @racket[lens-join/list], except that the views of the given
|
||||||
|
lenses are put in an instance of the @racket[struct-id] struct instead
|
||||||
|
of in a list.
|
||||||
|
@lenses-unstable-examples[
|
||||||
|
(struct foo (a b) #:transparent)
|
||||||
|
(define lens (lens-join/struct foo first-lens third-lens))
|
||||||
|
(lens-view lens '(1 2 3))
|
||||||
|
(lens-set lens '(1 2 3) (foo 'a 'b))
|
||||||
|
]
|
||||||
|
Struct fields in a @racket[lens-join/struct] form can also be
|
||||||
|
specified by keywords, in any order, and even with some fields specied
|
||||||
|
by position and some by keywords:
|
||||||
|
@lenses-unstable-examples[
|
||||||
|
(struct foo (a b) #:transparent)
|
||||||
|
(lens-view (lens-join/struct foo first-lens third-lens) '(1 2 3))
|
||||||
|
(lens-view (lens-join/struct foo #:a first-lens #:b third-lens) '(1 2 3))
|
||||||
|
(lens-view (lens-join/struct foo #:b third-lens #:a first-lens) '(1 2 3))
|
||||||
|
(lens-view (lens-join/struct foo first-lens #:b third-lens) '(1 2 3))
|
||||||
|
]}
|
Loading…
Reference in New Issue
Block a user