Coder Social home page Coder Social logo

safety-lens's Introduction

safety-lens

Join the chat at https://gitter.im/hallettj/safety-lens

Type-safe, functional lens library in JavaScript. This is basically a port of some of the concepts from the Haskell lens library. Safety-lens goes best with Flow.

A lens is used to focus in on a specific piece of a data structure. Using a lens, that piece can be read or updated. For example:

import { get, set } from 'safety-lens'
import { prop } from 'safety-lens-native'

let obj = { foo: 1, bar: 2 }

// Get a value
assert( get(prop('bar'), obj) === 2 )

obj = set(prop('bar'), 3, obj)

// Set a value
assert( get(prop('bar'), obj) === 3 )

The function call prop('bar') creates a lens that focuses on the bar property of any object.

get takes a lens and an object, and returns a reference to the focused piece of the object. So get(prop('bar'), obj) returns 2.

set takes a lens, a new value, and an object, and replaces the focused piece of the object with the new value. Or to be more precise, set creates a copy of the object in which the focused piece has been replaced with the new value. In the example above, set(prop('bar'), 3, obj) creates a new object that sets the bar property to 3, and keeps the foo property set to 1.

This is obviously more complicated than writing the equivalent expressions obj.bar or obj.bar = 3. But lenses do come with several advantages:

  • Lenses perform immutable updates: you get an updated copy of a data structure, while the original is untouched. This means that lenses pair nicely with immutable data libraries like Immutable or Mori, and support functional frameworks, such as Redux reducers.

  • Lenses can be composed to focus on deeply nested pieces of a data structure. Updating a deeply-nested, immutable data structure by hand is painful - but lenses make it easy.

  • Lenses provide type safety. Immutable has methods getIn, setIn; and Mori has equivalent functions. These are invaluable for working with deeply nested data structures. But there is no type checker available today that can check the type of a value returned from one of these functions, or that can check that appropriate types are used in updates. Lenses do the same job, but with dependable type-checking using Flow.

  • Lenses provide encapsulation. When writing a library or module, you can export lenses, but keep the details of your data structures hidden.

Documentation

Please refer to these topics for more information:

Install

npm install --save safety-lens

Building from source

Run:

$ yarn install && make

Requires yarn and GNU Make.

Examples of usage

Getting and setting nested values

import { get, set } from 'safety-lens'
import { prop } from 'safety-lens-native'

let obj = { foo: 1, bar: 2 }

// Get a value
assert( get(prop('bar'), obj) === 2 )

obj = set(prop('bar'), 3, obj)

// Set a value
assert( get(prop('bar'), obj) === 3 )

Transforming nested values with a function

import { over } from 'safety-lens'
import { prop } from 'safety-lens-native'

let obj = { foo: 1, bar: 2 }

obj = over(prop('bar'), x => x * 2, obj)

assert( obj.bar === 4 )

Composing lenses

Imagine a program with values of this type:

type Calendar = Array<{ date: Date, title: string }>

const events = [
  { date: new Date(), title: 'get coffee' },
  { date: new Date(), title: 'plan day' }
]

To construct a lens that can focus on the title of the first event in a calendar list:

import { compose, lookup } from 'safety-lens'
import { index, prop } from 'safety-lens-native'

const firstEventLens = index(0)
const titleLens = prop('title')

const firstEventTitleLens = compose(firstEventLens, titleLens)

assert( lookup(firstEventTitleLens, events) === 'get coffee' )

A lens might focus on multiple pieces within a data structure simultaneously. To operate on all events in a calendar:

import { over } from 'safety-lens'
import { traverse } from 'safety-lens-native'

const dateLens = prop('date')

const allDatesLens = compose(traverse, dateLens)

// Moves all events forward by one day.
const rescheduled = over(
  allDatesLens,
  date => new Date(Number(date) + 24 * 60 * 60 * 1000),
  events
)

safety-lens's People

Contributors

hallettj avatar greenkeeperio-bot avatar gitter-badger avatar

Stargazers

Roman avatar

Watchers

James Cloos avatar Evgeny Kochetkov avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.