On this page:
1.1 Lens Construction
lens?
make-lens
let-lens
1.2 Viewing and Setting
lens-view
lens-set
lens-view/  list
lens-set/  list
1.3 Lens Laws
1.4 Transforming Values With Lenses
lens-transform
lens-transform/  list
1.5 Lens Contracts
lens/  c
6.2.901.900

1 Core Lens Forms

1.1 Lens Construction

procedure

(lens? v)  boolean?

  v : any/c
Predicate for lenses.

procedure

(make-lens getter setter)  lens?

  getter : (-> target/c view/c)
  setter : (-> target/c view/c target/c)
Given a getter and a setter, constructs a lens defined on values satisfying target/c and viewing values satisfying view/c. The getter must accept a target and return the lens’s view. The setter must accept a target and a new view, and return a new target with its view replaced with the new view.

Examples:

> (define (set-first lst v)
    (list* v (rest lst)))
> (set-first '(1 2 3) 'a)

'(a 2 3)

> (define first-lens (make-lens first set-first))
> (lens-view first-lens '(1 2 3))

1

> (lens-set first-lens '(1 2 3) 'a)

'(a 2 3)

syntax

(let-lens (view-id context-id) lens-expr target-expr body ...)

Given a lens and a target, constructs the view and the context of the target through the lens and binds them to view-id and context-id respectively. The context is a function that accepts a new view and sets the target’s view to the new view. The context is conceptually a function representing the "hole" formed by abstracting the view of the target.

Example:

> (let-lens (view context) first-lens '(1 2 3)
    (printf "View is ~a\n" view)
    (context 'a))

View is 1

'(a 2 3)

1.2 Viewing and Setting

procedure

(lens-view lens target)  view/c

  lens : lens?
  target : target/c
Extracts the view of target with lens. Essentially a getter function.

Example:

> (lens-view first-lens '(1 2 3))

1

procedure

(lens-set lens target new-view)  target/c

  lens : lens?
  target : target/c
  new-view : view/c
Sets the view of target to new-view using lens. Essentially a setter function.

Example:

> (lens-set first-lens '(1 2 3) 'a)

'(a 2 3)

procedure

(lens-view/list target lens ...)  view/c

  target : target/c
  lens : lens?
Like lens-view, except that it takes multiple lenses and returns a list of views.

Example:

> (lens-view/list '(a b c d e f g)
                  first-lens fourth-lens fifth-lens)

'(a d e)

procedure

(lens-set/list target lens new-view ... ...)  target/c

  target : target/c
  lens : lens?
  new-view : view/c
Like lens-set, except that it can take multiple lenses-value pairs. If the view of two of the lenses overlap, the later views overwrite the earlier ones.

Examples:

> (lens-set/list '(1 2 3 4 5)
                 first-lens 10
                 third-lens 300)

'(10 2 300 4 5)

> (lens-set/list '(1 2 3)
                 first-lens 'a
                 first-lens 'b)

'(b 2 3)

1.3 Lens Laws

While make-lens allows lenses to be constructed from arbitrary getters and setters, these getters and setters should obey some algebraic laws in order for a lens to be a proper lens. A lens that does not obey the lens laws for all values it can focus on is an improper lens. The lens laws formalize some standard intuitions for how getters and setters "ought" to work. The laws for lenses are:

For those familiar with getters and setters in OO languages, none of these should be surprising other than the requirement that lenses be pure. The purity of lenses allows them to be composed more effectively and reasoned about more easily than an impure equivalent of lenses.

All lenses provided by this library are proper unless otherwise stated. There is no enforcement or contract that lenses constructed with functions from this library will always be proper, but individual functions may provide conditional guarantees about their interactions with improper lenses and the lens laws

1.4 Transforming Values With Lenses

procedure

(lens-transform lens target transformer)  target/c

  lens : lens?
  target : target/c
  transformer : (-> view/c view/c)
Transforms the view of target through the given lens with the transformer function. Equivalent to getting the view of target through lens, passing that value to transformer, then setting the view of target to the return value of calling transformer with the old view.

Example:

> (lens-transform first-lens '(1 2 3) number->string)

'("1" 2 3)

procedure

(lens-transform/list target    
  lens    
  transformer ...    
  ...)  target/c
  target : target/c
  lens : lens?
  transformer : (-> view/c view/c)
Like lens-transform, except that it can take multiple lenses-transformer pairs in the same way as lens-set* and later transformations overwrite earlier ones in the same way.

Example:

> (lens-transform/list '(1 2 3 4 5)
                       first-lens number->string
                       third-lens (λ (x) (* 100 x)))

'("1" 2 300 4 5)

1.5 Lens Contracts

procedure

(lens/c target/c view/c)  contract?

  target/c : contract?
  view/c : contract?
A contract constructor for lenses. The target/c contract is used for the second argument in (lens-view lens target), the second argument and the return value of (lens-set lens target view), for example, the view/c contract is used for the return value of (lens-view lens target) and the third argument of (lens-set lens target view), as well as other places where targets or views of the lens are used as inputs or outputs.