3 Traversals
(require glass/traversal) | package: glass |
A traversal is a type of optic for focusing on several parts of a subject at once. A traversal is built from a getter function, which extracts a list of foci from the subject, and a setter function, which takes a subject and a list of replacement foci and builds a new subject. Traversals are not allowed to change the number of foci when replacing them: if a traversal’s getter views 10 foci in a subject, then the traversal’s setter will only accept lists of exactly 10 replacement foci.
procedure
(traversal? v) → boolean?
v : any/c
procedure
(make-traversal #:getter getter #:setter setter [ #:counter counter #:name name]) → traversal? getter : (-> any/c immutable-vector?) setter : (-> any/c immutable-vector? any/c)
counter : (-> any/c natural?) = (λ (suject) (immutable-vector-length (getter subject))) name : (or/c interned-symbol? #f) = #f
(define-tuple-type player (name x y)) (define player-coordinates (make-traversal #:getter (λ (p) (immutable-vector (player-x p) (player-y p))) #:setter (λ (p xy) (player (player-name p) (vector-ref xy 0) (vector-ref xy 1))) #:counter (λ (_) 2) #:name 'player-coordinates))
> (traversal-get-all player-coordinates (player "Catherine" 2 7)) '#(2 7)
> (traversal-set-all player-coordinates (player "Catherine" 2 7) (list 0 0)) (player "Catherine" 0 0)
procedure
(traversal/c subject-contract foci-contract) → contract? subject-contract : contract? foci-contract : contract?
3.1 Using Traversals
procedure
(traversal-get-all traversal subject) → immutable-vector?
traversal : traversal? subject : any/c
procedure
(traversal-set-all traversal subject foci) → any/c
traversal : traversal? subject : any/c foci : (sequence/c any/c)
procedure
(traversal-count traversal subject) → natural?
traversal : traversal? subject : any/c
procedure
(traversal-map traversal subject mapper) → any/c
traversal : traversal? subject : any/c mapper : (-> any/c any/c)
> (traversal-map string-traversal "hello" char-upcase) "HELLO"
procedure
(traversal-clear traversal subject replacement) → any/c traversal : traversal? subject : any/c replacement : any/c
> (traversal-clear string-traversal "hello" #\x) "xxxxx"
procedure
(traversal-reverse traversal subject) → any/c
traversal : traversal? subject : any/c
> (traversal-reverse string-traversal "hello") "olleh"
3.2 Predefined Traversals
value
value
value
> (traversal-count string-traversal "hello") 5
> (traversal-get-all string-traversal "hello") '#(#\h #\e #\l #\l #\o)
value
> (traversal-get-all identity-traversal 6) '#(6)
> (traversal-set-all identity-traversal 6 (list 100)) 100
3.3 More Traversal Constructors
procedure
(traversal-pipe traversal ...) → traversal?
traversal : traversal?
(define list-of-strings-traversal (traversal-pipe list-traversal string-traversal)) (define strings (list "hello" "darkness" "my" "old" "friend"))
> (traversal-map list-of-strings-traversal strings char-upcase) '("HELLO" "DARKNESS" "MY" "OLD" "FRIEND")
> (traversal-clear list-of-strings-traversal strings #\-) '("-----" "--------" "--" "---" "------")
> (traversal-reverse list-of-strings-traversal strings) '("dneir" "fdloymss" "en" "kra" "dolleh")
procedure
(subtraversal traversal inclusive-start [ exclusive-end]) → traversal? traversal : traversal? inclusive-start : natural? exclusive-end : (or/c natural? #f) = #f
> (traversal-clear (subtraversal string-traversal 2 8) "hello world" #\_) "he______rld"
procedure
(lens->traversal lens) → traversal?
lens : lens?
> (define entry.key-traversal (lens->traversal entry.key)) > (traversal-get-all entry.key-traversal (entry 'grapes 4)) '#(grapes)
> (traversal-set-all entry.key-traversal (entry 'grapes 4) (list 'apples)) (entry 'apples 4)
procedure
(prism->traversal prism) → traversal?
prism : prism?
> (define success-traversal (prism->traversal success-prism)) > (traversal-get-all success-traversal (success 5)) '#(5)
> (traversal-set-all success-traversal (success 5) (list 10)) (success 10)