https://github.com/chocolateboy/box
Put a value in a box
https://github.com/chocolateboy/box
bind box chain compose container functional functor iife pipe pipeline point-free pointfree tacit
Last synced: 2 months ago
JSON representation
Put a value in a box
- Host: GitHub
- URL: https://github.com/chocolateboy/box
- Owner: chocolateboy
- License: mit
- Created: 2021-01-20T23:51:44.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2021-08-01T15:13:07.000Z (about 4 years ago)
- Last Synced: 2025-07-08T16:18:02.023Z (3 months ago)
- Topics: bind, box, chain, compose, container, functional, functor, iife, pipe, pipeline, point-free, pointfree, tacit
- Language: JavaScript
- Homepage:
- Size: 252 KB
- Stars: 1
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.md
Awesome Lists containing this project
README
# box
[](https://github.com/chocolateboy/box/actions?query=workflow%3Atest)
[](https://www.npmjs.org/package/@chocolatey/box)- [NAME](#name)
- [FEATURES](#features)
- [INSTALLATION](#installation)
- [SYNOPSIS](#synopsis)
- [DESCRIPTION](#description)
- [Why?](#why)
- [Why not?](#why-not)
- [EXPORTS](#exports)
- [default](#default)
- [Box<T>](#box-class)
- [Static Methods](#static-methods)
- [constructor](#constructor)
- [Box.of](#boxof)
- [Instance Methods](#instance-methods)
- [map](#map)
- [tap](#tap)
- [then](#then)
- [value](#value)
- [DEVELOPMENT](#development)
- [COMPATIBILITY](#compatibility)
- [SEE ALSO](#see-also)
- [VERSION](#version)
- [AUTHOR](#author)
- [COPYRIGHT AND LICENSE](#copyright-and-license)# NAME
Box - put a value in a box
# FEATURES
- no dependencies
- < 170 B minified + gzipped
- fully typed (TypeScript)
- CDN builds (UMD) - [jsDelivr][], [unpkg][]# INSTALLATION
$ npm install @chocolatey/box
# SYNOPSIS
```javascript
import $ from '@chocolatey/box'$(42) // Box<42>
$(42).value() // 42
$(42).map(it => it + 1) // Box<43>
$(42).tap(console.log) // Box<42>
$(42).then(it => it + 1) // 43
$(42, it => it + 1) // 43// "*.tar.gz" -> "*.gz"
const untar = name => $(name)
.map(it => it.split('.'))
.tap(it => it.splice(1, 1))
.then(it => it.join('.'))untar('package.tar.gz') // "package.gz"
```# DESCRIPTION
Box puts a value in a container which exposes a handful of methods to
facilitate piping values through a series of functions.It provides a lightweight implementation of the [box pattern][], which allows
the right-to-left flow of function composition to be expressed via the
left-to-right syntax of method chaining familiar from jQuery, Lodash, promises
etc.## compose
```javascript
import R from 'ramda'const fn1 = value => baz(bar(foo(value)))
const fn2 = R.compose(baz, bar, foo)
```## box
```javascript
import $ from '@chocolatey/box'const fn = value => $(value).map(foo).map(bar).then(baz)
```## Why?
Because:
> composition and dot chaining are the same, and dot chaining is more ergonomic
> in JavaScript— [Brian Lonsdorf](https://frontendmasters.com/courses/hardcore-js-v2/composition-is-dot-chaining/)
## Why not?
If you're using Babel, pipelines can be written natively with features such as
the [pipeline operator][], [do expressions][] and [partial application][],
e.g.:```javascript
import { tap } from 'lodash'const untar = name =>
name.split('.')
|> tap(#, it => it.splice(1, 1))
|> #.join('.')
```If you're already using Lodash/Underscore or similar, you can use their
built-in methods to implement pipelines, e.g.:```javascript
import _ from 'lodash'const untar = name =>
_(name)
.split('.')
.tap(it => it.splice(1, 1))
.join('.')
```# EXPORTS
## default
- **Type**:
- `(value: T, fn: (value: T) => R): R`
- `(value: T): Box`
- **Aliases**: $, box```javascript
import $ from '@chocolatey/box'$(42) // Box<42>
$(42, it => it + 1) // 43
```The default export is a function which either takes a value and puts it in a
box (via [`Box.of`](#boxof)) or takes a value and a function and applies the
function to the value.The latter provides a convenient shorthand for passing an argument to an IIFE,
e.g.:### imperative
```javascript
const counter = (function () {
let count = 0
return () => ++count
})()counter() // 1
counter() // 2
counter() // 3
```### IIFE
```javascript
const counter = (function (count) { return () => ++count })(0)
```### Box
```javascript
const counter = $(0, count => () => ++count)
```### Static Methods
#### constructor
- **Type**: `new (value: T) => Box`
```javascript
import { Box } from '@chocolatey/box'const box = new Box(42) // Box<42>
```Creates a new Box instance containing the supplied value.
#### Box.of
- **Type**: `(value: T) => Box`
```javascript
import { Box } from '@chocolatey/box'const box = Box.of(42) // Box<42>
const boxes = [1, 2, 3].map(Box.of) // [Box<1>, Box<2>, Box<3>]
```Returns a new [`Box`](#box-class) instance containing the supplied value.
Note that `of` is a function which returns a Box instance rather than a method
which returns an instance of its invocant, so the following are equivalent:```javascript
class MyBox extends Box {} // XXX missing `of` overrideconst array = [1, 2]
array.map(it => Box.of(it)) // [Box<1>, Box<2>]
array.map(it => MyBox.of(it)) // [Box<1>, Box<2>]
array.map(Box.of) // [Box<1>, Box<2>]
array.map(MyBox.of) // [Box<1>, Box<2>]
```### Instance Methods
#### map
- **Type**: `(fn: (value: T) => U): Box`
```javascript
import $ from '@chocolatey/box'$(42).map(it => it + 1) // Box<43>
```Applies the supplied function to the value and returns a new box containing the
result.#### tap
- **Type**: `(fn: (value: T) => void): this`
```javascript
import $ from '@chocolatey/box'$(42).tap(console.log) // Box<42>
```Applies the supplied function to the value and returns the original box (the
invocant). Useful to insert side effects, logging etc. into a pipeline without
changing the value.#### then
- **Type**: `(fn: (value: T) => U): U`
```javascript
import $ from '@chocolatey/box'$(42).then(it => it + 1) // 43
```Returns the result of applying the supplied function to the value.
#### value
- **Type**: `(fn?: (value: T) => void): T`
```javascript
import $ from '@chocolatey/box'$(42).value() // 42
$(42).value(console.log) // 42
```Returns the value. If an optional function is supplied, it is applied to the
value before the value is returned. This is similar to [`tap`](#tap), except
the value is returned rather than the box.# DEVELOPMENT
## NPM Scripts
The following NPM scripts are available:
- build - compile the library for testing and save to the target directory
- build:doc - generate the README's TOC (table of contents)
- build:release - compile the library for release and save to the target directory
- clean - remove the target directory and its contents
- rebuild - clean the target directory and recompile the library
- repl - launch a node REPL with the library loaded
- test - recompile the library and run the test suite
- test:run - run the test suite
- typecheck - sanity check the library's type definitions# COMPATIBILITY
- [Maintained Node.js versions](https://github.com/nodejs/Release#readme) and compatible browsers
# SEE ALSO
## Libraries
- [fcf](https://github.com/GianlucaGuarini/fcf) - a functional alternative to control-flow statements such as `if`, `switch` and `while`
- [fp-ts](https://www.npmjs.com/package/fp-ts) - functional programming in TypeScript## Videos
- [Brian Lonsdorf - Create linear data flow with container style types (Box)](https://egghead.io/lessons/javascript-linear-data-flow-with-container-style-types-box)
- [Brian Lonsdorf - Oh Composable World!](https://www.youtube.com/watch?v=SfWR3dKnFIo)# VERSION
1.2.0
# AUTHOR
[chocolateboy](mailto:chocolate@cpan.org)
# COPYRIGHT AND LICENSE
Copyright © 2021 by chocolateboy.
This is free software; you can redistribute it and/or modify it under the terms
of the [MIT license](https://opensource.org/licenses/MIT).[arrow functions]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
[box pattern]: https://mostly-adequate.gitbooks.io/mostly-adequate-guide/content/ch08.html
[comma operator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator
[do expressions]: https://github.com/tc39/proposal-do-expressions
[jsDelivr]: https://cdn.jsdelivr.net/npm/@chocolatey/box@1.2.0/dist/index.umd.min.js
[partial application]: https://github.com/tc39/proposal-partial-application
[pipeline operator]: https://github.com/tc39/proposal-pipeline-operator
[unpkg]: https://unpkg.com/@chocolatey/box@1.2.0/dist/index.umd.min.js