Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

partial.lenses

Package Overview
Dependencies
Maintainers
1
Versions
180
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

partial.lenses

Ramda compatible lenses

  • 0.2.1
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
4.3K
decreased by-8.26%
Maintainers
1
Weekly downloads
 
Created
Source

npm version

This library provides a collection of Ramda compatible partial (dealing with undefined results) lenses. The intention is to make modification or editing of JSON data convenient and compositional.

Motivation

Consider the following REPL session using Ramda 0.19.1:

> R.set(R.lensPath(["x", "y"]), 1, {})
{ x: { y: 1 } }
> R.set(R.compose(R.lensProp("x"), R.lensProp("y")), 1, {})
TypeError: Cannot read property 'y' of undefined
> R.view(R.lensPath(["x", "y"]), {})
undefined
> R.view(R.compose(R.lensProp("x"), R.lensProp("y")), {})
TypeError: Cannot read property 'y' of undefined
> R.set(R.lensPath(["x", "y"]), undefined, {x: {y: 1}})
{ x: { y: undefined } }
> R.set(R.compose(R.lensProp("x"), R.lensProp("y")), undefined, {x: {y: 1}})
{ x: { y: undefined } }

One might assume that R.lensPath([p1, ..., pN]) is equivalent to R.compose(R.lensProp(p1), ..., R.lensProp(pN)), but that is not the case.

Usage

The lenses and operations on lenses are accessed via the default import:

import L from "partial.lenses"

Operations on lenses

For convenience, you can access basic operations on lenses via the default import L:

  • L.lens(get, set) is the same as R.lens(get, set) (see lens).
  • L.over(lens, x2x, s) is the same as R.over(lens, x2x, s) (see over).
  • L.set(lens, x, s) is the same as R.set(lens, x, s) (see set).
  • L.view(lens, s) is the same as R.view(lens, s) (see view).

Shorthand composition and lifting

The default import, L, is also a shorthand function for lens composition (see compose) and lifting. The semantics can be described as

L(l1, ..., lN) === R.compose(lift(l1), ..., lift(lN))

where

const lift = l => {
  switch (typeof l) {
  case "string": return L.prop(l)
  case "number": return L.index(l)
  default:       return l
  }
}

Lenses

L.prop(string)

L.prop(string) is much like R.lensProp(string) (see lensProp), but composes as a partial lens:

  • When viewing an undefined property or an undefined object, the result is undefined.
  • When setting property to undefined, the property is removed from the result. If the result would be an empty object, the whole result will be undefined.

Examples:

> L.set(L("x", "y"), undefined, {x: {y: 1}})
undefined
> L.set(L("x", "y"), 2, {x: {y: 1}})
{ x: { y: 2 } }
> L.set(L("x", "y"), undefined, {x: {y: 1}, z: 3})
{ z: 3 }
> L.set(L("x", "y"), 2, {x: {y: 1}, z: 3})
{ x: { y: 2 }, z: 3 }
> L.view(L("x", "y"), undefined)
undefined

L.index(integer)

L.index(integer) is like R.lensIndex(integer) (see lensIndex), but composes as a partial lens:

  • When viewing an undefined array index or an undefined array, the result is undefined.
  • When setting an array index to undefined, the element is removed from the resulting array, shifting all higher indices down by one. If the result would be an array without indices (ignoring length), the whole result will be undefined.

L.find(predicate)

L.find(predicate) operates on arrays like L.index, but the index to be viewed is determined by finding the first element from the input array that matches the given unary predicate. When no matching element is found the effect is same as with R.index with the index set to the length of the array.

L.normalize(transform)

L.normalize(transform) maps the value with same given transform when viewed and set and implicitly maps undefined to undefined. More specifically, L.normalize(transform) is equivalent to R.lens(toPartial(transform), toPartial(transform)) where

const toPartial = transform => x => undefined === x ? x : transform(x)

The use case for normalize is to make it easy to determine whether, after a change, the data has actually changed. By keeping the data normalized, a simple R.equals comparison will do.

L.replace(inn, out)

L.replace(inn, out), when viewed, replaces the value inn with out and vice versa when set. Values are compared using R.equals (see equals).

Examples:

> L.view(L(L.replace(undefined, {type: "title", text: ""}),
           "text"),
         undefined)
""
> L.set(L(L.replace(undefined, {type: "title", text: ""}),
          "text"),
        "",
        {type: "title", text: "not empty"})
undefined

The use case for replace is to handle optional properties and elements.

Keywords

FAQs

Package last updated on 01 Feb 2016

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc