8.2

### 3Traversals

 (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 v : any/c
A predicate for traversals.

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
Constructs a traversal named name.

Examples:
 (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?
A contract combinator for traversals. Creates a contract that accepts traversals whose subjects are checked with subject-contract and whose foci are checked with foci-contract.

#### 3.1Using Traversals

 procedure(traversal-get-all traversal subject) → immutable-vector? traversal : traversal? subject : any/c
Traverses subject with traversal and returns a list of the traversal’s foci.

 procedure(traversal-set-all traversal subject foci) → any/c traversal : traversal? subject : any/c foci : (sequence/c any/c)
Traverses subject with traversal and replaces each focus with an element of foci, returning a new subject. If foci does not contain the same number of elements as the traversed subject, a contract error is raised.

 procedure(traversal-count traversal subject) → natural? traversal : traversal? subject : any/c
Traverses subject with traversal and counts the traversal’s foci.

 procedure(traversal-map traversal subject mapper) → any/c traversal : traversal? subject : any/c mapper : (-> any/c any/c)
Traverses subject with traversal and updates each focus with mapper, returning a new subject with the updated foci.

Example:
 > (traversal-map string-traversal "hello" char-upcase) "HELLO"

procedure

 (traversal-clear traversal subject replacement) → any/c
traversal : traversal?
subject : any/c
replacement : any/c
Traverses subject with traversal and sets each focus to replacement, returning a new subject with the updated foci.

Example:
 > (traversal-clear string-traversal "hello" #\x) "xxxxx"

 procedure(traversal-reverse traversal subject) → any/c traversal : traversal? subject : any/c
Traverses subject with traversal and reverses the order of the traversed foci, returning a new subject with the reversed foci.

Example:
 > (traversal-reverse string-traversal "hello") "olleh"

#### 3.2Predefined Traversals

 value
A traversal that traverses the elements of a list.

 value
A traversal that traverses the elements of a vector. The traversal accepts both mutable and immutable vectors, but it only produces immutable vectors.

 value
A traversal that traverses the characters of a string. The traversal accepts both mutable and immutable strings, but it only produces immutable strings.

Examples:
 > (traversal-count string-traversal "hello") 5 > (traversal-get-all string-traversal "hello") '#(#\h #\e #\l #\l #\o)

 value
The identity traversal. Traverses only one element of the subject, and that element is the subject itself.

Examples:
 > (traversal-get-all identity-traversal 6) '#(6) > (traversal-set-all identity-traversal 6 (list 100)) 100

#### 3.3More Traversal Constructors

 procedure(traversal-pipe traversal ...) → traversal? traversal : traversal?
Joins each traversal to the next, building a composed traversal that traverses subjects by traversing the subject with the first traversal, then traversing each of those traversed elements with the second traversal, and so on for each traversal in left-to-right order. If only one traversal is given, it is returned directly. If no traversals are given, identity-traversal is returned.

Examples:
 (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
Limits traversal to only operate on the elements between inclusive-start and exclusive-end. If exclusive-end is false, the subtraversal includes all elements after inclusive-start.

Example:
 > (traversal-clear (subtraversal string-traversal 2 8) "hello world" #\_) "he______rld"

 procedure(lens->traversal lens) → traversal? lens : lens?
Converts lens into a traversal that always focuses on exactly one part of the subject using lens.

Examples:
 > (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?
Converts prism into a traversal that has either zero foci, if prism does not match the subject, or one focus if prism does match the subject.

Examples:
 > (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)