From dde85c9796836e1eafe99bee37e3422f9b9e2bcd Mon Sep 17 00:00:00 2001 From: AlexKnauth Date: Mon, 31 Aug 2015 15:32:55 -0400 Subject: [PATCH 1/5] add transformer-lens closes https://github.com/jackfirth/lens/issues/201 --- unstable/lens/transformer.rkt | 79 +++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 unstable/lens/transformer.rkt diff --git a/unstable/lens/transformer.rkt b/unstable/lens/transformer.rkt new file mode 100644 index 0000000..a8ca86b --- /dev/null +++ b/unstable/lens/transformer.rkt @@ -0,0 +1,79 @@ +#lang sweet-exp racket/base + +provide transformer-lens + +require fancy-app + lens/private/base/main + racket/match + "isomorphism/base.rkt" +module+ test + require lens/private/list/main + rackunit + "isomorphism/data.rkt" + "mapper.rkt" + +;; transformer-lens : (Lens (Outer Inner) Inner) (Lens A B) -> (Lens (Outer A) (Outer B)) +(define (transformer-lens lens transformer-lens) + (match transformer-lens + [(make-isomorphism-lens transformer inverse) + ;; transformer : A -> B + ;; inverse : B -> A + (make-isomorphism-lens + (lens-transform lens _ transformer) ; (Outer A) -> (Outer B) + (lens-transform lens _ inverse))] ; (Outer B) -> (Outer A) + [transformer-lens + ;; get : (Outer A) -> (Outer B) + (define (get tgt) + ;; transformer : A -> B + (define (transformer a) + (lens-view transformer-lens a)) + (lens-transform lens tgt transformer)) + ;; set : (Outer A) (Outer B) -> (Outer A) + (define (set tgt nvw) + ;; a : A + (define a (lens-view lens tgt)) + ;; transformer : B -> A + (define (transformer b) + (lens-set transformer-lens a b)) + (lens-transform lens nvw transformer)) + (make-lens get set)])) + +module+ test + (define first-sym->str + (transformer-lens first-lens symbol->string-lens)) + (check-equal? (lens-view first-sym->str '(a b c)) + '("a" b c)) + (check-equal? (lens-set first-sym->str '(a b c) '("a" b c)) + '(a b c)) + (check-equal? (lens-set first-sym->str '(a b c) '("z" b c)) + '(z b c)) + (check-equal? (lens-set first-sym->str '(a b c) '("z" bee sea)) + '(z bee sea)) + (check-equal? (lens-view first-sym->str (lens-set first-sym->str '(a b c) '("z" bee sea))) + '("z" bee sea)) + (define trans-second-first + (transformer-lens second-lens first-lens)) + (check-equal? (lens-view trans-second-first '(1 (2 3) 4)) + '(1 2 4)) + (check-equal? (lens-set trans-second-first '(1 (2 3) 4) '(1 2 4)) + '(1 (2 3) 4)) + (check-equal? (lens-set trans-second-first '(1 (2 3) 4) '(1 b 4)) + '(1 (b 3) 4)) + (check-equal? (lens-set trans-second-first '(1 (2 3) 4) '(a b c)) + '(a (b 3) c)) + (check-equal? (lens-view trans-second-first + (lens-set trans-second-first '(1 (2 3) 4) '(a b c))) + '(a b c)) + (define (rekey-alist-lens key->new-key-lens) + (mapper-lens (transformer-lens car-lens key->new-key-lens))) + (check-equal? (lens-view (rekey-alist-lens symbol->string-lens) '((a . 1) (b . 2) (c . 3))) + '(("a" . 1) ("b" . 2) ("c" . 3))) + (check-equal? (lens-set (rekey-alist-lens symbol->string-lens) + '((a . 1) (b . 2) (c . 3)) + '(("a" . 10) ("b" . 200) ("c" . 3000))) + '((a . 10) (b . 200) (c . 3000))) + (check-equal? (lens-set (rekey-alist-lens symbol->string-lens) + '((a . 1) (b . 2) (c . 3)) + '(("one" . 10) ("two" . 200) ("three" . 3000))) + '((one . 10) (two . 200) (three . 3000))) + From c9fa6fb8ea78142e0f529835f82d2026fb90af4b Mon Sep 17 00:00:00 2001 From: AlexKnauth Date: Mon, 31 Aug 2015 15:48:38 -0400 Subject: [PATCH 2/5] provide and document transformer-lens --- unstable/lens/main.rkt | 1 + unstable/lens/main.scrbl | 1 + unstable/lens/transformer.scrbl | 26 ++++++++++++++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 unstable/lens/transformer.scrbl diff --git a/unstable/lens/main.rkt b/unstable/lens/main.rkt index 4393467..6c69a5e 100644 --- a/unstable/lens/main.rkt +++ b/unstable/lens/main.rkt @@ -13,4 +13,5 @@ "struct-nested.rkt" "sublist.rkt" "syntax.rkt" +"transformer.rkt" "view-set.rkt" diff --git a/unstable/lens/main.scrbl b/unstable/lens/main.scrbl index 10d51a5..2a2d1e9 100644 --- a/unstable/lens/main.scrbl +++ b/unstable/lens/main.scrbl @@ -26,6 +26,7 @@ this library being backwards-compatible. "struct-nested.scrbl" "sublist.scrbl" "syntax.scrbl" + "transformer.scrbl" "view-set.scrbl" ) diff --git a/unstable/lens/transformer.scrbl b/unstable/lens/transformer.scrbl new file mode 100644 index 0000000..f6275e5 --- /dev/null +++ b/unstable/lens/transformer.scrbl @@ -0,0 +1,26 @@ +#lang scribble/manual + +@(require lens/private/doc-util/main) + +@title{Lenses that transform subpieces} + +@defmodule[unstable/lens/transformer] + +@defproc[(transformer-lens [lens lens?] [transform-lens lens?]) lens?]{ +Creates a lens that transforms the subpiece of the target that @racket[lens] +views with @racket[transform-lens]. + +@racketblock[(lens-view (transformer-lens lens transform-lens) target)] +is equivalent to: +@racketblock[(lens-transform lens target (λ (v) (lens-view transform-lens v)))] + +@lens-unstable-examples[ + (define first-sym->str + (transformer-lens first-lens symbol->string-lens)) + (lens-view first-sym->str '(a b c)) + (lens-set first-sym->str '(a b c) '("a" b c)) + (lens-set first-sym->str '(a b c) '("z" b c)) + (lens-set first-sym->str '(a b c) '("z" bee sea)) + (lens-view first-sym->str (lens-set first-sym->str '(a b c) '("z" bee sea))) +]} + From 95d6df290d5e4bc2fbaee7b20c1a05bb28e659cf Mon Sep 17 00:00:00 2001 From: AlexKnauth Date: Tue, 1 Sep 2015 16:01:05 -0400 Subject: [PATCH 3/5] add transformer-lens* --- unstable/lens/transformer.rkt | 45 ++++++++++++++++++++++++--------- unstable/lens/transformer.scrbl | 15 +++++++++++ 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/unstable/lens/transformer.rkt b/unstable/lens/transformer.rkt index a8ca86b..c4fb335 100644 --- a/unstable/lens/transformer.rkt +++ b/unstable/lens/transformer.rkt @@ -1,10 +1,13 @@ #lang sweet-exp racket/base provide transformer-lens + transformer-lens* require fancy-app lens/private/base/main + lens/private/compound/thrush racket/match + unstable/sequence "isomorphism/base.rkt" module+ test require lens/private/list/main @@ -38,6 +41,11 @@ module+ test (lens-transform lens nvw transformer)) (make-lens get set)])) +(define (transformer-lens* . lenses/transformers) + (apply lens-thrush + (for/list ([args (in-slice 2 lenses/transformers)]) + (apply transformer-lens args)))) + module+ test (define first-sym->str (transformer-lens first-lens symbol->string-lens)) @@ -51,18 +59,18 @@ module+ test '(z bee sea)) (check-equal? (lens-view first-sym->str (lens-set first-sym->str '(a b c) '("z" bee sea))) '("z" bee sea)) - (define trans-second-first - (transformer-lens second-lens first-lens)) - (check-equal? (lens-view trans-second-first '(1 (2 3) 4)) - '(1 2 4)) - (check-equal? (lens-set trans-second-first '(1 (2 3) 4) '(1 2 4)) - '(1 (2 3) 4)) - (check-equal? (lens-set trans-second-first '(1 (2 3) 4) '(1 b 4)) - '(1 (b 3) 4)) - (check-equal? (lens-set trans-second-first '(1 (2 3) 4) '(a b c)) - '(a (b 3) c)) - (check-equal? (lens-view trans-second-first - (lens-set trans-second-first '(1 (2 3) 4) '(a b c))) + (define trans-second-first/third-second + (transformer-lens* second-lens first-lens third-lens second-lens)) + (check-equal? (lens-view trans-second-first/third-second '(1 (2 3) (4 5))) + '(1 2 5)) + (check-equal? (lens-set trans-second-first/third-second '(1 (2 3) (4 5)) '(1 2 5)) + '(1 (2 3) (4 5))) + (check-equal? (lens-set trans-second-first/third-second '(1 (2 3) (4 5)) '(1 b 5)) + '(1 (b 3) (4 5))) + (check-equal? (lens-set trans-second-first/third-second '(1 (2 3) (4 5)) '(a b c)) + '(a (b 3) (4 c))) + (check-equal? (lens-view trans-second-first/third-second + (lens-set trans-second-first/third-second '(1 (2 3) (4 5)) '(a b c))) '(a b c)) (define (rekey-alist-lens key->new-key-lens) (mapper-lens (transformer-lens car-lens key->new-key-lens))) @@ -76,4 +84,17 @@ module+ test '((a . 1) (b . 2) (c . 3)) '(("one" . 10) ("two" . 200) ("three" . 3000))) '((one . 10) (two . 200) (three . 3000))) + (define (rek+v-alist-lens key->new-key-lens value->new-value-lens) + (mapper-lens (transformer-lens* car-lens key->new-key-lens cdr-lens value->new-value-lens))) + (check-equal? (lens-view (rek+v-alist-lens symbol->string-lens number->string-lens) + '((a . 1) (b . 2) (c . 3))) + '(("a" . "1") ("b" . "2") ("c" . "3"))) + (check-equal? (lens-set (rek+v-alist-lens symbol->string-lens number->string-lens) + '((a . 1) (b . 2) (c . 3)) + '(("a" . "10") ("b" . "200") ("c" . "3000"))) + '((a . 10) (b . 200) (c . 3000))) + (check-equal? (lens-set (rek+v-alist-lens symbol->string-lens number->string-lens) + '((a . 1) (b . 2) (c . 3)) + '(("one" . "10") ("two" . "200") ("three" . "3000"))) + '((one . 10) (two . 200) (three . 3000))) diff --git a/unstable/lens/transformer.scrbl b/unstable/lens/transformer.scrbl index f6275e5..c47df3a 100644 --- a/unstable/lens/transformer.scrbl +++ b/unstable/lens/transformer.scrbl @@ -24,3 +24,18 @@ is equivalent to: (lens-view first-sym->str (lens-set first-sym->str '(a b c) '("z" bee sea))) ]} +@defproc[(transformer-lens* [lens lens?] [transform-lens lens?] ... ...) lens?]{ +A multi-arg version of @racket[transformer-lens], analogous to +@racket[lens-transform/list]. It is equivalent to +@racket[(lens-thrush (transformer-lens lens transform-lens) ...)]. +@lens-unstable-examples[ + (define first-sym->str/second-num->str + (transformer-lens* first-lens symbol->string-lens second-lens number->string-lens)) + (lens-view first-sym->str/second-num->str '(a 2 c)) + (lens-set first-sym->str/second-num->str '(a 2 c) '("a" "2" c)) + (lens-set first-sym->str/second-num->str '(a 2 c) '("z" "3" c)) + (lens-set first-sym->str/second-num->str '(a 2 c) '("z" "3" sea)) + (lens-view first-sym->str/second-num->str + (lens-set first-sym->str/second-num->str '(a 2 c) '("z" "3" sea))) +]} + From 96c501dca4e9930cddca6628023b239227e9a601 Mon Sep 17 00:00:00 2001 From: AlexKnauth Date: Fri, 4 Sep 2015 23:27:03 -0400 Subject: [PATCH 4/5] rename to lens-zoom --- unstable/lens/main.rkt | 2 +- unstable/lens/main.scrbl | 2 +- unstable/lens/{transformer.rkt => zoom.rkt} | 30 +++++++++---------- .../lens/{transformer.scrbl => zoom.scrbl} | 20 ++++++------- 4 files changed, 27 insertions(+), 27 deletions(-) rename unstable/lens/{transformer.rkt => zoom.rkt} (81%) rename unstable/lens/{transformer.scrbl => zoom.scrbl} (62%) diff --git a/unstable/lens/main.rkt b/unstable/lens/main.rkt index 6c69a5e..80a7828 100644 --- a/unstable/lens/main.rkt +++ b/unstable/lens/main.rkt @@ -13,5 +13,5 @@ "struct-nested.rkt" "sublist.rkt" "syntax.rkt" -"transformer.rkt" "view-set.rkt" +"zoom.rkt" diff --git a/unstable/lens/main.scrbl b/unstable/lens/main.scrbl index 2a2d1e9..933da27 100644 --- a/unstable/lens/main.scrbl +++ b/unstable/lens/main.scrbl @@ -26,7 +26,7 @@ this library being backwards-compatible. "struct-nested.scrbl" "sublist.scrbl" "syntax.scrbl" - "transformer.scrbl" "view-set.scrbl" + "zoom.scrbl" ) diff --git a/unstable/lens/transformer.rkt b/unstable/lens/zoom.rkt similarity index 81% rename from unstable/lens/transformer.rkt rename to unstable/lens/zoom.rkt index c4fb335..996843c 100644 --- a/unstable/lens/transformer.rkt +++ b/unstable/lens/zoom.rkt @@ -1,7 +1,7 @@ #lang sweet-exp racket/base -provide transformer-lens - transformer-lens* +provide lens-zoom + lens-zoom* require fancy-app lens/private/base/main @@ -15,40 +15,40 @@ module+ test "isomorphism/data.rkt" "mapper.rkt" -;; transformer-lens : (Lens (Outer Inner) Inner) (Lens A B) -> (Lens (Outer A) (Outer B)) -(define (transformer-lens lens transformer-lens) +;; lens-zoom : (Lens (Outer Inner) Inner) (Lens A B) -> (Lens (Outer A) (Outer B)) +(define (lens-zoom zoom-lens transformer-lens) (match transformer-lens [(make-isomorphism-lens transformer inverse) ;; transformer : A -> B ;; inverse : B -> A (make-isomorphism-lens - (lens-transform lens _ transformer) ; (Outer A) -> (Outer B) - (lens-transform lens _ inverse))] ; (Outer B) -> (Outer A) + (lens-transform zoom-lens _ transformer) ; (Outer A) -> (Outer B) + (lens-transform zoom-lens _ inverse))] ; (Outer B) -> (Outer A) [transformer-lens ;; get : (Outer A) -> (Outer B) (define (get tgt) ;; transformer : A -> B (define (transformer a) (lens-view transformer-lens a)) - (lens-transform lens tgt transformer)) + (lens-transform zoom-lens tgt transformer)) ;; set : (Outer A) (Outer B) -> (Outer A) (define (set tgt nvw) ;; a : A - (define a (lens-view lens tgt)) + (define a (lens-view zoom-lens tgt)) ;; transformer : B -> A (define (transformer b) (lens-set transformer-lens a b)) - (lens-transform lens nvw transformer)) + (lens-transform zoom-lens nvw transformer)) (make-lens get set)])) -(define (transformer-lens* . lenses/transformers) +(define (lens-zoom* . lenses/transformers) (apply lens-thrush (for/list ([args (in-slice 2 lenses/transformers)]) - (apply transformer-lens args)))) + (apply lens-zoom args)))) module+ test (define first-sym->str - (transformer-lens first-lens symbol->string-lens)) + (lens-zoom first-lens symbol->string-lens)) (check-equal? (lens-view first-sym->str '(a b c)) '("a" b c)) (check-equal? (lens-set first-sym->str '(a b c) '("a" b c)) @@ -60,7 +60,7 @@ module+ test (check-equal? (lens-view first-sym->str (lens-set first-sym->str '(a b c) '("z" bee sea))) '("z" bee sea)) (define trans-second-first/third-second - (transformer-lens* second-lens first-lens third-lens second-lens)) + (lens-zoom* second-lens first-lens third-lens second-lens)) (check-equal? (lens-view trans-second-first/third-second '(1 (2 3) (4 5))) '(1 2 5)) (check-equal? (lens-set trans-second-first/third-second '(1 (2 3) (4 5)) '(1 2 5)) @@ -73,7 +73,7 @@ module+ test (lens-set trans-second-first/third-second '(1 (2 3) (4 5)) '(a b c))) '(a b c)) (define (rekey-alist-lens key->new-key-lens) - (mapper-lens (transformer-lens car-lens key->new-key-lens))) + (mapper-lens (lens-zoom car-lens key->new-key-lens))) (check-equal? (lens-view (rekey-alist-lens symbol->string-lens) '((a . 1) (b . 2) (c . 3))) '(("a" . 1) ("b" . 2) ("c" . 3))) (check-equal? (lens-set (rekey-alist-lens symbol->string-lens) @@ -85,7 +85,7 @@ module+ test '(("one" . 10) ("two" . 200) ("three" . 3000))) '((one . 10) (two . 200) (three . 3000))) (define (rek+v-alist-lens key->new-key-lens value->new-value-lens) - (mapper-lens (transformer-lens* car-lens key->new-key-lens cdr-lens value->new-value-lens))) + (mapper-lens (lens-zoom* car-lens key->new-key-lens cdr-lens value->new-value-lens))) (check-equal? (lens-view (rek+v-alist-lens symbol->string-lens number->string-lens) '((a . 1) (b . 2) (c . 3))) '(("a" . "1") ("b" . "2") ("c" . "3"))) diff --git a/unstable/lens/transformer.scrbl b/unstable/lens/zoom.scrbl similarity index 62% rename from unstable/lens/transformer.scrbl rename to unstable/lens/zoom.scrbl index c47df3a..881007e 100644 --- a/unstable/lens/transformer.scrbl +++ b/unstable/lens/zoom.scrbl @@ -4,19 +4,19 @@ @title{Lenses that transform subpieces} -@defmodule[unstable/lens/transformer] +@defmodule[unstable/lens/zoom] -@defproc[(transformer-lens [lens lens?] [transform-lens lens?]) lens?]{ -Creates a lens that transforms the subpiece of the target that @racket[lens] +@defproc[(lens-zoom [zoom-lens lens?] [transform-lens lens?]) lens?]{ +Creates a lens that transforms the subpiece of the target that @racket[zoom-lens] views with @racket[transform-lens]. -@racketblock[(lens-view (transformer-lens lens transform-lens) target)] +@racketblock[(lens-view (lens-zoom zoom-lens transform-lens) target)] is equivalent to: -@racketblock[(lens-transform lens target (λ (v) (lens-view transform-lens v)))] +@racketblock[(lens-transform zoom-lens target (λ (v) (lens-view transform-lens v)))] @lens-unstable-examples[ (define first-sym->str - (transformer-lens first-lens symbol->string-lens)) + (lens-zoom first-lens symbol->string-lens)) (lens-view first-sym->str '(a b c)) (lens-set first-sym->str '(a b c) '("a" b c)) (lens-set first-sym->str '(a b c) '("z" b c)) @@ -24,13 +24,13 @@ is equivalent to: (lens-view first-sym->str (lens-set first-sym->str '(a b c) '("z" bee sea))) ]} -@defproc[(transformer-lens* [lens lens?] [transform-lens lens?] ... ...) lens?]{ -A multi-arg version of @racket[transformer-lens], analogous to +@defproc[(lens-zoom* [zoom-lens lens?] [transform-lens lens?] ... ...) lens?]{ +A multi-arg version of @racket[lens-zoom], analogous to @racket[lens-transform/list]. It is equivalent to -@racket[(lens-thrush (transformer-lens lens transform-lens) ...)]. +@racket[(lens-thrush (lens-zoom zoom-lens transform-lens) ...)]. @lens-unstable-examples[ (define first-sym->str/second-num->str - (transformer-lens* first-lens symbol->string-lens second-lens number->string-lens)) + (lens-zoom* first-lens symbol->string-lens second-lens number->string-lens)) (lens-view first-sym->str/second-num->str '(a 2 c)) (lens-set first-sym->str/second-num->str '(a 2 c) '("a" "2" c)) (lens-set first-sym->str/second-num->str '(a 2 c) '("z" "3" c)) From da77504a7636a00411440084f2a10e95a527765b Mon Sep 17 00:00:00 2001 From: AlexKnauth Date: Fri, 4 Sep 2015 23:33:40 -0400 Subject: [PATCH 5/5] add contracts for lens-zoom and lens-zoom* --- unstable/lens/zoom.rkt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/unstable/lens/zoom.rkt b/unstable/lens/zoom.rkt index 996843c..eb21f17 100644 --- a/unstable/lens/zoom.rkt +++ b/unstable/lens/zoom.rkt @@ -1,11 +1,15 @@ #lang sweet-exp racket/base -provide lens-zoom - lens-zoom* +require racket/contract/base +provide + contract-out + lens-zoom (-> lens? lens? lens?) + lens-zoom* (->* [] #:rest (listof2 lens? lens?) lens?) require fancy-app lens/private/base/main lens/private/compound/thrush + lens/private/util/list-pair-contract racket/match unstable/sequence "isomorphism/base.rkt"