• Stars
    star
    73
  • Rank 419,380 (Top 9 %)
  • Language
    Racket
  • License
    Other
  • Created about 9 years ago
  • Updated over 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A Racket package for creating and composing pure functional lenses

lens Build Status codecov Scribble Docs

A Racket package for creating and composing pure functional lenses.

raco pkg install lens (require lens)

What on earth are lenses?

A lens is a value that can be used to focus on a small subpiece of some larger structure. A lens splits some data structure into two pieces - a view, which is some small isolated component of the data structure, and a context, which is everything else. The context can have a new view placed into it. This makes a lens act like a pure functional getter and setter:

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

Lenses are first class values and pure functional, so they can be abstracted over and functions that operate on lenses can be created. For instance, given a lens its view can be "updated":

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

Additionaly, lenses are separate values from the objects they operate on, so they can be manipulated independently of any specific data. Functions can construct lenses, and operations can combine lenses. This allows for lens composition:

> (define first-of-b-key-lens (lens-compose first-lens (hash-ref-lens 'b)))
> (define a-hash (hash 'a '(1 2 3) 'b '(10 20 30) 'c '(100 200 300)))
> (lens-view first-of-b-key-lens a-hash)
10
> (lens-set first-of-b-key-lens a-hash 'foo)
#hash((a . (1 2 3)) (b . (foo 20 30)) (c . (100 200 300)))

Lenses can also be joined together to form compound lenses that view many things:

> (define first-third-fifth-lens (lens-join/list first-lens third-lens fifth-lens))
> (lens-view first-third-fifth-lens '(1 2 3 4 5 6))
'(1 3 5)
> (lens-set first-third-fifth-lens '(1 2 3 4 5 6) '(a b c))
'(a 2 b 4 c 6)

Lenses can also be extended to operate on some new data structure:

> (define first-of-each-lens (map-lens first-lens))
> (lens-view first-of-each-lens '((1 2) (3 4) (5 6)))
'(1 3 5)
> (lens-set first-of-each-lens '((1 2) (3 4) (5 6)) '(a b c))
'((a 2) (b 4) (c 6))

See the documentation for a full API reference

So when would I want to use lenses?

Lenses are most effective when you're dealing with the "giant ball of state" problem. When you have a large amount of state you need to pass around between code written in a functional style, it's difficult to update and manage it due to the lack of mutation "magically" updating your entire object graph when a function changes a small part of it. Lenses allow code to break down and manipulate portions of this state, simplifying interactions and updates.

In particular, consider using lenses if you find yourself doing any of the following:

  • Using a giant complex piece of state that most pieces of code only care about a small part of
  • Writing struct-copy a lot
  • Converting some hairy data structure into another one, manipulating it, then turning it back
  • Wishing you could treat data X as if it were a Y, i.e. "I wish this struct was a list so I could map over it easily"
  • Creating structs that have nested struct instances inside them.

For a more in depth introduction, see The Lens Guide. For detailed API documentation, see The Lens Reference.

More Repositories

1

pyramda

Python package supporting heavy functional programming through currying. Translation of the Ramda library from javascript to python.
Python
128
star
2

rebellion

A collection of core libraries for Racket
Racket
79
star
3

resyntax

A Racket refactoring engine
Racket
45
star
4

point-free

Collection of forms and higher order functions that assist function composition and definition of functions in a point-free style
Racket
24
star
5

racket-request

Package for simplifying HTTP requests and writing integration tests of REST-ful APIs in Racket
Racket
23
star
6

racket-mock

Mocking library for Racket
Racket
22
star
7

racket-package-template

My personal template repository for Racket packages
Racket
13
star
8

racket-net2

The networking library that Racketeers deserve
Racket
13
star
9

racket-package-ci-action

A GitHub Action for building and testing Racket packages
Shell
12
star
10

glass

An optics (lenses, prisms, traversals, etc.) library for Racket.
Racket
10
star
11

j-notation

An exploration into an alternate surface syntax.
Racket
9
star
12

compose-app

Racket syntax for Haskell-style function composition
Racket
8
star
13

syntax-warn

Define syntax warnings for Racket code
Racket
8
star
14

racket-fixture

An experimental Racket library that adds test fixtures to RackUnit
Racket
7
star
15

racket-disposable

An experimental Racket library providing an abstraction for values associated with external resources that allows automatic resource pooling, per-thread virtual construction, and monadic composition
Racket
7
star
16

type-conventions

A Typed Racket package that allows for function arguments to be declared as having a default type
Racket
6
star
17

doc-coverage

A Racket package for inspecting and testing the number of documented exports of a module
Racket
6
star
18

package-analysis

A Racket package for analyzing the Racket package ecosystem
Racket
6
star
19

racket-expect

A Racket library for defining expectations on values, unit testing, and creating quality error messages
Racket
6
star
20

atomichron

A Racket microbenchmarking library
Racket
5
star
21

command-line-ext

A Racket package providing an extensible way to define command line scripts
Racket
5
star
22

chess

A Racket package for playing chess
Racket
5
star
23

planning

A Racket package for automated planning
Racket
5
star
24

compact-annotations

A Typed Racket package for writing compact polymorphic (and non-polymorphic) function annotations with a syntax similar to that of Haskell's type annotations
Racket
5
star
25

generic-syntax-expanders

A Racket package for creating macros with built-in support for defining sub-macros within them, similar to match expanders
Racket
5
star
26

htdf

How to Design Functions, the function design recipe from the textbook How to Design Programs.
Racket
4
star
27

decorator

An experimental compile-time Racket adaptation of python's decorators
Racket
4
star
28

racket-retry

A Racket package for retrying operations with exponential backoff, jitter, and backoff restarting
Racket
4
star
29

regex-machine

A Racket package for Russ Cox's regex machine language
Racket
4
star
30

predicates

Deprecated. A racket package for creating predicates in a point-free style.
Racket
3
star
31

miniracksis

A Racket port of the Minithesis property testing library
Racket
3
star
32

docker-racket-catalog

Dockerized Racket webserver running a Racket package catalog
Racket
3
star
33

fiberweb

An experiment in cooperative concurrency for Racket.
Racket
2
star
34

http2

A (wildly unimplemented) http2 client and server for Racket
Racket
2
star
35

lambda-calculus

A racket language for lambda calculus
Racket
2
star
36

jackfirth.github.io

HTML
1
star
37

syntax-render

A Racket package for rendering syntax objects into strings
Racket
1
star
38

racket-syntax-lang

Racket library for easy creation of simple #langs
Racket
1
star
39

docker-auth

Authentication layer as Docker containers
Python
1
star
40

advent-of-code

Racket
1
star
41

codeclass-fp-js

Exercises for Functional Programming in Javascript
JavaScript
1
star
42

advent-of-code-2019

My attempts at solving the Advent of Code 2019 puzzles
Racket
1
star