ES Functional Programming
Improve functional programming in JavaScript
This is a Browserify transform with several features (some non-standard) to improve writing JavaScript in a functional style. This repo also serves as a place to discuss moving JavaScript in a more functional direction, and how to impliment that here.
Features
- The good ES6+ features (inspired from
es2020
andes2040
)- Template literals
- Arrow functions
- Block scoping
- Destructuring
- Default params
- Rest/spread
- Shorthand properties (e.g.
{ foo, bar }
) - Object rest/spreads (e.g.
{ ...foo, bar: 123 }
)
- Non-standard features
-
Pipe operator over
pull-stream
- Implicit return value
- React JSX with
pragma: 'h'
out-of-the-box - Static type checking with Flow
-
Pipe operator over
Here is an example of piping, with implicit return, and cloning an object using spread:
function foo (options) {
options = { bar: 123, ...options }
foobar(options)
| bazqux()
| oofrab()
}
Install
npm install --save esfp
# with yarn
yarn add esfp
Usage
Load as a browserify transform in whatever tool you use. For example, with CLI:
browserify entry.js -g esfp > out.js
Or with browserify
b.transform('esfp')
Or pull-bundle
(for a more functional solution 😉)
bundle('app.js', [ 'esfp' ])
Pipe operator
To use the pipe operator, you should first be familiar with pull-stream
, as it will let you do cool things like async and partial pipelines.
Here we just transform foo | bar | ...
chains into pull(foo, bar, ...)
calls:
values([1, 2, 3])
| map(x => x * 3)
| drain(console.log)
// into:
pull(
values([1, 2, 3])
map(x => x * 3),
drain(console.log)
)
You can also create streams from other streams (known as a "partial"):
const foo =
infinity()
| map(x => x * 100)
| filter(x => x % 2)
// Use it in another pipeline:
foo | drain(console.log)
See babel-plugin-pull
for more details
Implicit return value
You don't need to return the last value in a function:
function foo (x) {
x % 1 !== 0
}
This is especially useful in combination with the pipe operator and partial streams:
function foo ({ modifier }) {
values([ 1, 2, 3 ])
| map(x => x * modifier)
}
foo({ modifier: 3 })
| drain(console.log)
See babel-plugin-implicit-return
for more details
h
JSX pragma With transform-react-jsx
+ pragma: 'h'
you have more high-level sytnax creating views with functions.
function foo (e, data) {
<div onclick=${e}>${data}</div>
}
You can use this with librares like hyperapp
instead of having to load babelify
+ the plugin.
Static type checking
This plugin automatically strips Flow types for static type checking.
Note: It does not actually check the types. Use something like ESLint for that aspect.
function foo (bar: number, baz: number): number {
return bar + baz
}
This could be replaced with a more functional-style type checking:
// foo : number, number
function foo (bar, baz) {
return bar + baz
}
Let me know your suggestions
Maintained by Jamen Marz (See on Twitter and GitHub for questions & updates)