natural-lenses

This module is (when required) or exports as default (when imported) a Function accepting an arbitrary number of keys and returning a Lens.

A Lens is a way to safely apply the indexing (i.e. square-bracket) operator repeatedly, and to clone-with-changes a complex value to assist programming in an immutable-data style.

In addition to the properties enumerated here, all error classes are also exposed as properties or named exports.

Source:
Properties:
Name Type Description
asyncLogging function

Documentation

at_maybe symbol

Key for method implementing retrieval from a container

clone symbol

Key for method implementing cloning of a container with modifications

eachFound function

Documentation

Factory function

Class for customized lens creation

fuse function

Documentation

isLens symbol

Key for testing objects for "lens-ness"

JsContainerFactory function

Class for customized container creation

jsContainers Object

JsContainerFactory for standard JavaScript containers (Map and Array)

maybeDo function

Documentation

nfocal function

Construct a multifocal lens

polyfillImmutable function

Documentation

setLogger function

Documentation

Step function

Class for customized Lens steps

Parameters:
Name Type Attributes Description
key * <repeatable>

A name or index to use in successive subscripting (i.e. square bracket) operations

Returns:

The constructed lens

Type
Lens

Members

(constant) at_maybe :symbol

Source:

This constant is a key used for querying a method from container objects of type function(*): Maybe.<*>. The value passed to this method will be a key from a Lens -- the kind of value that should be passed for a conceptual "indexing" of the container. For Object, this is a string property name. For Array, this is an integer index, where negative values count backward from the end of the Array. For Map, this uses Map.prototype.has and Map.prototype.get.

Type:
  • symbol

(constant) clone :symbol

Source:

This constant is a key used for querying a method from container objects of type function({set: {0: *, 1: *}?, spliceOut: *?}): *. The intent of the method is to clone the container with some kind of alteration -- either a key/index set to the given value in the clone, or a key/index deleted from the clone.

If the operation description passed contains a set property, the value of that property should be an Array where element 0 is a key or index into the container and element 1 is the value to set (cf. arguments to Map.prototype.set).

If the operation description passed contains a spliceOut property, the value of that property should be a key or index to delete from the container. Where possible, the result should be to leave the container in a state where container[at_maybe](key) returns {} (a Nothing). This is specifically a problem for immutable.List, which offers only a dense presentation of elements: every non-negative index less than size is a valid and "contained" entry. The implementation provided by this library for implementing this method on immutable.List sets the value of the entry in the clone to undefined.

In the provided implemenation for Array, negative indexes are interpreted counting backward from the end of the Array, as with Array.prototype.slice.

Symbol.species is honored for determining the constructor used for the clone; Object is a special case that defaults to Object if Symbol.species is not present.

Type:
  • symbol

(constant) isLens :symbol

Source:

This property is set on every kind of object to be recognized by this library as implementing lens-like behavior. Setting this property to any truthy value on your own objects will cause this library to treat it in many ways like a Lens.

Type:
  • symbol

Methods

asyncLogging(engine)

Enable asynchronous-context awareness for logger assignment

Source:
Since:
  • 2.2.0

Logging configuration is usually a global activity. However, there are cases where some specific section of the code needs to redirect its logging to a different handler.

In many languages and environments, this diversion of logging events would be handled with a thread- or fiber-local variable. JavaScript — with its extensive use of closures and asynchronous callbacks/Promises — needs to associate the logging diversion with the asynchronous context of the code setting the logger. There is, however, no standard way to do this.

To bridge this gap, natural-lenses provides asynchronous context engines which can be configured on demand. Setting the engine does not change the current logger, but can allow code to change the logger in a more local fashion. Configuring the appropriate asynchronous context engine makes setLogger.forBlock much more adept at getting logging events to the correct handler in asynchronous contexts.

Engines

Engine name Implementation
node Uses require('async_hooks').AsyncLocalStorage
Parameters:
Name Type Description
engine string

Name of the engine to use

Returns:

The module (for chainable configuration)

(generator) eachFound(maybe_val) → {FoundPair}

Iterate over Maybe monad contained value(s)

Source:
See:

When called on the result of getting a multifocal into a Maybe monad, this function iterates found values (and only the found values), yielding the pair of the value and index for each, like the arguments to the callback of Array.prototype.forEach if it used "rest" syntax, e.g.

values.forEach((...pair) => {
  const [value, index] = pair;
  // do something with index and value
});

When called on the get_maybe-result of an ArrayNFocal, the index 1 value of each yielded Array will be an integer index; with an ObjectNFocal, the index 1 value of each yeilded Array will be a string key.

This function can also be applied to a Maybe monad value obtained from a monofocal optic (e.g. a Lens), in which case it yields either a single element array containing the value if the input holds a just property and does not yield, otherwise. It is more flexible to apply maybeDo or Optic#getting, as these allow separate handling of the Nothing case.

Parameters:
Name Type Description
maybe_val Maybe.<*>

Maybe monad of value or iterable value

Yields:
Pairs of value and key
Type
FoundPair

fuse(…optic) → {Lens|OpticArray}

Fuse multiple optics into a single, sequential application

Source:

To understand the slot reference of the returned optic, consider the getting model: optics[0] will be applied to the input data, and for all other optics (i > 0), optics[i] will be applied to the result from optics[i - 1]. In other words, each optic gets something within the optic to its left, with the leftmost getting from the input data. Modifications affect the same slot.

If all optics are Lenses, the result will be a Lens. This does not apply for Lens-derived objects (e.g. from Factories) — if such are passed, the result will always be an OpticArray.

Parameters:
Name Type Attributes Description
optic Optic <repeatable>

Optic object to fuse

Returns:

A single Optic joining the optics

Type
Lens | OpticArray

maybeDo(maybe, then, orElseopt) → {U}

Conditionally execute a function based on the construction of a Maybe

Source:
See:

This function resembles an if statement around the "Just-ness" of a Maybe value: the then Function gets called if maybe has a just and the orElse Function if not. Because of the usual intent of this conditional situation, maybe.just value is passed to then if then is called.

Whichever of then or orElse is called, its return value becomes the return value of this function call.

Parameters:
Name Type Attributes Description
maybe Maybe.<T>

The input value determining which of the following arguments is invoked

then function

The function executed with the just value of maybe, if present

orElse function <optional>

The function executed if maybe contains no just property

Returns:

The result type of the invoked function

Type
U

nfocal(lenses) → {ArrayNFocal|ObjectNFocal}

Construct a multifocal lens

Source:

Where a standard lens looks at a single slot within a JSONic object, a multifocal lens consists of multiple lenses (standard or multifocal) whose results are aggregated into a single value, which can be a dictionary-like Object or an Array.

Pass an Array of lenses to create a multifocal lens that outputs an Array, where the position of each lens in the input Array corresponds to the output position of the data (when getting with the multifocal lens). When getting in a Maybe context (#get_maybe), the result will always be an Object with a just property, though some elements of the Array may be empty.

Pass an Object with lens values to create a multifocal lens outputting an Object, which will bear the same properties as the input Object and whose values are the values in the data referenced by the corresponding lens (when getting using this multifocal lens).

Be aware that the xformInClone method on these kinds of multifocal lenses works differently from a basic Lens, since multifocals can have a "stereoscopic" view of data. Instead of a single transformation function, xformInClone (and it's _maybe variant) accept an iterable of key/transform pairs (where the key is an integer index in the case of an Array multifocal). This allows full control over the order in which transformations are applied to the input data, resolving the issue of "stereoscopic conflict".

Parameters:
Name Type Description
lenses Array.<Optic> | Object.<string, Optic>

Collection of Lenses to combine

Returns:
Type
ArrayNFocal | ObjectNFocal

polyfillImmutable(containerType)

Add lensing support methods to an Immutable type

Source:

Adds mixin methods for supporting lenses to the given Immutable container type.

Parameters:
Name Type Description
containerType function

Target container type for support

setLogger(logger) → {Logger}

Set a custom logger

Source:
Since:
  • 2.2.0
Properties:
Name Type Description
forBlock module:natural-lenses~BlockLogger

Set the logger only for the duration of the callback

Calling this function changes the "current logger"...in some regard. If asyncLogging has not been called, then the global current logger is changed; if it has been called, the specific engine invoked determines what is set. In the case of the node engine, logger becomes the receiver for subsequent logging calls in the synchronous context and any asynchronous contexts subsequently spawned from it. When the node engine is in use and this function is called from an asynchronous context, the logging receiver change is local to that context but propagates to any asynchronous contexts it spawns.

Parameters:
Name Type Description
logger Logger

Custom logger to use, with interface like console

Returns:

The previous logger

Type
Logger

Type Definitions

BlockLogger(logger, body) → {T}

Temporarily log to a different logger during callback

Source:
Since:
  • 2.2.0
See:

Calling this method temporarily redirects logging output to logger during the execution of body.

Asynchronicity without asyncLogging

If body registers callbacks that complete after it returns, logging calls will return to targeting the status quo ante logger (or whatever logger happens to be current at the time). There is no way for this library to detect this has happend and warn about pending callbacks logging to a different logger.

If body returns a thenable (i.e. an object with a then property, like a Promise), logger will remain the target logger until the result fulfills or rejects. A warning will also be logged because the target logger for the entire process is changed by this usage.

Asynchronicity with asyncLogging

If asyncLogging has been called to install an asynchronous-context-aware engine, then logger will be the target logger during the execution of body and for any asynchronous execution starting within body, whether via callback or thenable.

Parameters:
Name Type Description
logger Logger

Custom logger to use, with interface like console

body function

Callback to execute, logging to logger; receives no arguments and returns T

Returns:

Return value from body

Type
T