Lens

Lens

new Lens(…key)

Class for operating immutably on a specific "slot" in complex data

Source:
Properties:
Name Type Description
keys Array.<*>

Indexing/subscripting values to be applied successively to subjects of this lens

A Lens constructed as let l = new Lens('address', 'street', 0) represents a certain slot within a complex subject value. If we had a record

const record = {
  address: {
    street: ["123 Somewhere Ln.", "Apt. 42"]
  }
};

then applying our lens with l.get(record) would evaluate to "123 Somewhere Ln.".

NOTE: If a key of a Lens is a negative number and the container accessed at that level is an Array, the negtive index works like Array.prototype.slice, counting from the end of the Array.

But Lenses offer more functionality than retrieval of values from a deeply structured value — they can create a minimally cloned value deeply equal to the subject but for the slot targeted by the lens and strictly equal but for the slot targeted by the lens and the nodes in the input subject traversed to reach that slot in the subject's tree.

When constructing a modified clone, it is possible that some step of the Lens will target a slot within a container-not-existing-in-subject. In this case, the container to be created is intuited from the key that would access it: an Array if the key is a number, otherwise an Object. Alternative container construction can be specified via Factory or Step.

Typically, instances are constructed by calling the Function exported from natural-lenses (if required) or its default export (if imported), conventionally named lens.

Parameters:
Name Type Attributes Description
key * <repeatable>

A value to use in an application of subscripting (i.e. square bracket operator)

Extends

Methods

(static) fuse()

Source:

Combine the effects of multiple Lenses

It is preferred to use module:natural-lenses#fuse

binding(methodName, options) → {Object}

DRYly bind a Function to the Object from which it was obtained

Source:
Overrides:
See:

This method is a way to avoid duplicating code referencing an object within options.on when 1) obtaining the reference to the method's function, and 2) binding that method to the object from which it was accessed.

By default, the binding is lazy — the target of the lens within on is evaluated when the resulting Function is invoked (though on itself is bound in this call). To bind the resulting Function to its target immediately when this method is called, set options.bindNow to true.

Examples
const data = {question: "What is the ultimate answer?"};
const qStarts = lens('question').binding('startsWith', {on: data});
qStarts('What') // => true
data.question = "Why is a raven like a writing desk?";
qStarts('What') // => false
qStarts('Why') // => true
const data = {question: "What is the ultimate answer?"};
const qStarts = lens('question').binding('startsWith', {on: data, bindNow: true});
qStarts('What') // => true
data.question = "Why is a raven like a writing desk?";
qStarts('What') // => true (because qStarts bound to the target of the lens when `binding` was called)
Parameters:
Name Type Description
methodName string | symbol
options Object
Properties
Name Type Attributes Default Description
on *

The subject of the Function binding; becomes this for the result

bindNow boolean <optional>
false

Bind to the Optic's target within on rather than binding to on

orThrow * <optional>

OptionalThrow if the slot referenced does not contain a Function; has precedence over or

or function <optional>

FallbackBindingResult, a Function to return if the slot referenced does not contain a Function

Returns:

A Function binding the methodName of the target of this optic to the target of this optic

Type
Object

bound(subject, optionsopt) → {function}

DRYly bind a Function to the Object from which it was obtained

Source:

Use this to avoid the dreaded Javascript binding repetition of x.y.z.fn.bind(x.y.z). Instead, use lens('y', 'z', 'fn').bound(x).

Parameters:
Name Type Attributes Description
subject *

The input structured data

options Object <optional>
Properties
Name Type Attributes Default Description
bindNow boolean <optional>
true

Bind to the target of this lens with subject now rather than when the result function is invoked

orThrow * <optional>

OptionalThrow if the slot referenced does not contain a Function; has precedence over or

or function <optional>

FallbackBindingResult, a Function to return if the slot referenced does not contain a Function

Returns:

A Function bound to the previous object in the chain used to access the Function

Type
function

get(subject, …tail) → {*}

Get the value of this slot within subject data

Source:
Overrides:

If tail is given, then #get() is called on the result of getting this slot from subject, passing the spread of tail. This eliminates repeated use of .get in code. The chaining fails, returning undefined, if this slot in subject is not a lens-like object (as indicated by a truthy lens.isLens property).

Parameters:
Name Type Attributes Description
subject *

The data to query

tail * <repeatable>

Additional subjects for repeated application

Returns:

The value of this slot, or undefined if this slot is not present in subject

Type
*

get_maybe(subject, …tail) → {Maybe.<*>}

Get a combination of presence and value of this slot

Source:
Overrides:

This implements the Maybe monad (familiar from Haskell), where Nothing is represented as an empty Object and Just is represented as an Object with a just property containing the value in the slot.

If tail is given and getting this slot from from subject yields a Lens (as indicated by a truthy lens.isLens property), then #get_maybe() is called on that Lens, passing the spread of tail. If the value of this slot is not a Lens, the result is an empty Object.

Parameters:
Name Type Attributes Description
subject *

The data to query

tail * <repeatable>

Additional subject for repeated application

Returns:

Empty Object if this slot is not present in subject, otherwise Object with just property containing value of this slot in subject

Type
Maybe.<*>

getIterable(subject, optionsopt) → {Iterable.<*>}

Get the (iterable) value of this slot within some subject data

Source:
Overrides:

If the slot does not exist within subject, this method returns an empty Array. If the slot within subject contains a non-iterable value, this method's behavior depends on orThrow. If orThrow is undefined, the behavior is the same as if the slot did not exist: an empty Array is returned. If orThrow is not undefined, orThrow is thrown; if orThrow is an Object, its noniterableValue property will be set to the slot's value before being thrown.

This method differs from Optic#get in that the returned value will always be iterable; thus, the return value of this method may safely be passed into any function expecting an iterable value. One example usage is constructing a Seq from the immutable package.

Strings, though iterable, are considered scalar values; if the targeted slot contains a string, the slot will be treated as non-iterable.

Parameters:
Name Type Attributes Description
subject *

The data to query

options Object <optional>
Properties
Name Type Attributes Description
orThrow * <optional>

OptionalThrow if the value of the slot exists but is not iterable

Returns:

An iterable of values from this slot (or an empty Array)

Type
Iterable.<*>

getting(subject, branches) → {T}

Conditionally evaluate functions depending on presence of slot

Source:
Overrides:

The presence of the slot determines whether branches.then or branches.else is evaluated, with the result being returned from this method. If the indicated property of branches is missing, then undefined is returned.

Parameters:
Name Type Description
subject *

The input structured data

branches Object
Properties
Name Type Attributes Description
then function <optional>

Function evaluated if slot is present in subject

else function <optional>

Function evaluated if slot is absent from subject

Returns:

The value computed by branches.then or branches.else, or undefined

Type
T

present(subject) → {Boolean}

Test for the presence of this slot in subject data

Source:
Overrides:
Parameters:
Name Type Description
subject *

The data to test

Returns:

Whether this slot is present in subject

Type
Boolean

setInClone(subject, newVal) → {T}

Clone subject, setting the value of this slot within the clone

Source:
Overrides:

"Minimally changed" means that reference-copies are used wherever possible while leaving subject unchanged, and that setting the slot to the strict- equal value it already has results in returning subject.

Parameters:
Name Type Description
subject T

The input structured data

newVal *

The new value to inject into the slot identified by this lens

Returns:

A minimally changed clone of subject with newVal in this slot

Type
T

thence(…key) → {Lens|OpticArray}

Build a "deeper" lens/optic

Source:
Overrides:

This method creates a new Optic that looks at finer detail than the Optic on which it was called. It either actually or effectively fuses a new Lens to the right of this optic, as with fuse.

Parameters:
Name Type Attributes Description
key * <repeatable>

A value to use in an application of subscripting (i.e. square bracket operator)

Returns:

An Optic that fuses this optic with a Lens looking at finer detail

Type
Lens | OpticArray

xformInClone(subject, fn, optsopt) → {T}

Clone the input, transforming the value within this slot with a function

Source:
Overrides:

If this slot is missing in subject, fn will not be called unless addMissing is true, in which case fn will be called with undefined.

"Minimally changed" means that reference-copies are used wherever possible while leaving subject unchanged, and that setting the slot to the strict- equal value it already has results in returning subject.

Parameters:
Name Type Attributes Description
subject T

The input structured data

fn function

The function that transforms the slot value

opts Object <optional>
Properties
Name Type Default Description
addMissinng Boolean false

Whether to add the slot if missing in subject

Returns:

A minimally changed clone of subject with fn applied to the value in this slot

Type
T

xformInClone_maybe(subject, fn) → {T}

Clone the input, transforming or deleting the Maybe value of this slot with a function

Source:
Overrides:

The value given to fn will be the result of Lens#get_maybe, which indicates absence of this slot in subject by omitting the just property, which otherwise contains the value of this slot in subject. The value returned by fn is the result that should be returned by calling Lens#get_maybe of this slot on the modified clone: if no just property is returned by fn, the slot is deleted from the clone, and the value of the just property is otherwise set for this slot in the clone.

This implements what would, in Haskell, be described as:

Json -> (Maybe Json -> Maybe Json) -> Json

"Minimally changed" means that reference-copies are used wherever possible while leaving subject unchanged, and that setting the slot to the strict- equal value it already has results in returning subject.

Parameters:
Name Type Description
subject T

The input structured data

fn function

The function transforming the Maybe value of the slot

Returns:

A minimally changed clone of subject with this slot transformed per fn

Type
T

xformIterableInClone(subject, fn, optionsopt) → {T}

Clone the input, transforming the iterable value within this slot with a function

Source:
Overrides:

If the slot does not exist within subject, fn is invoked on an empty Array. If the slot within subject contains a non-iterable value, this method's behavior depends on orThrow. If orThrow is undefined, the behavior is the same as if the slot did not exist: an empty Array is passed to fn. If orThrow is not undefined, orThrow is thrown; if orThrow is an Object, its noniterableValue property will be set to the slot's value before being thrown.

The primary differences between this method and Lens#xformInClone are that this method always passes an iterable value to fn and always calls fn even if the slot is missing or does not contain an iterable value (unless orThrow is given).

Strings, though iterable, are considered scalar values; if the targeted slot contains a string, the slot will be treated as non-iterable.

"Minimally changed" means that reference-copies are used wherever possible while leaving subject unchanged, and that setting the slot to the strict- equal value it already has results in returning subject.

Parameters:
Name Type Attributes Description
subject T

The input structured data

fn function

The function that transforms the (iterable) slot value

options Object <optional>
Properties
Name Type Attributes Description
orThrow * <optional>

OptionalThrow if the value of the slot exists but is not iterable

Returns:

A minimally changed clone of subject with the transformed value in this slot

Type
T