Transpiles function-bind call expressions to partially applied call expressions. Uses the invocation context to set the last parameter of the callee function.
Syntactically, the babel-plugin-syntax-function-bind
also allows the reader to read the functions in left to right order of application, rather than reading from the innermost expression out.
- Familiar with Ramda? This transpiler enables a syntactic sugar for pipe function.
- Coming from Clojure? This transpiler enables a syntactic sugar for thread-first macro.
BIG WARNING: This is a proof-of-concept. See Motivation.
Input:
apple
::foo('foo parameter 0', 'foo parameter 1')
::bar('bar parameter 0')
::baz('baz parameter 0');
Output:
baz(
'baz parameter 0',
bar(
'bar parameter 0',
foo(
'foo parameter 0',
'foo parameter 1',
apple
)
)
);
To make functional programming in JavaScript sweeter π§π¨π¦.
Help this proposal to get more attention by spreading the word (or retweet the original announcement)!
Participate in a reddit discussion to share your thoughts and suggestions.
There is no active proposal for this functionality.
I am looking for feedback. If there is sufficient interest, I will proceed with a proposal.
ECMAScript This-Binding Syntax proposal introduces a new operator ::
which performs this
binding and method extraction, i.e.
The following input:
foo::bar()::baz()
Becomes the following output:
var _context;
(_context = (_context = foo, bar).call(_context), baz).call(_context);
babel-plugin-transform-function-composition
uses the ::
operator to create a partially applied function such that the left hand side of the operator is set as the the first parameter to the target function on the right hand side, i.e.
The following input:
foo::bar()::baz()
Becomes the following output:
baz(bar(foo));
ECMAScript Pipeline Operator proposal introduces a new operator |>
which is a syntactic sugar on a function call with a single argument. In other words, sqrt(64)
is equivalent to 64 |> sqrt
.
The biggest difference between ::
and |>
is that the latter permits only a single parameter.
NOTE: There is no Babel transpiler for the Pipeline Operator proposal. See tc39/proposal-pipeline-operator#33
The ::
syntax conflicts with the This-Binding Syntax proposal. However, at the time of writing this This-Binding Syntax proposal remains in stage 0 without an active champion (see What's keeping this from Stage 1?). In the mean time, the syntax support has been added to Babel (babel-plugin-syntax-function-bind).
The reason for choosing the ::
operator for this proposal is to enable early adoption of this functionality.
NOTE: Should this implementation develop into a proposal, it is possible that an alternative syntax will be proposed (e.g.
->>
).
Bluebird is a promise library that provides non-standard utilities used to abstract common Promise
operations.
Here is an example of using Promise.map
and Promise.filter
:
import Promise from 'bluebird';
Promise
.resolve([
'foo',
'bar',
'baz'
])
.map((currentValue) => {
return currentValue.toUpperCase();
})
.filter((currentValue) => {
return currentValue.indexOf('B') === 0;
});
Bluebird achieves this by providing a custom implementation of Promise
object. This can be achieved by adding map
and filter
functions to the native Promise.prototype
.
Note: Augmenting the built-in prototype is considered an anti-pattern. This approach is mentioned only for the sake of completeness of the example.
You can use ::
to achieve an equivalent composition:
const map = async (callback, promise) => {
const values = await promise;
return values.map(callback);
};
const filter = async (callback, promise) => {
const values = await promise;
return values.filter(callback);
};
Promise
.resolve([
'foo',
'bar',
'baz'
])
::map((currentValue) => {
return currentValue.toUpperCase();
})
::filter((currentValue) => {
return currentValue.indexOf('B') === 0;
});
In both cases, the result of the operation is:
[
'BAR',
'BAZ'
]
Bluebird is heavy dependency (31Kb). Using function composition you have implemented equivalent functionality without the bundle size overhead.
Ramda is a functional flavor utility library. Ramda is designed to enable build functions as sequences of simpler functions, each of which transforms the data and passes it along to the next.
Here is an example of using R.pipe
to perform left-to-right function composition:
import {
assocPath,
pipe
} from 'ramda';
pipe(
assocPath(['repository', 'type'], 'git'),
assocPath(['repository', 'url'], 'https://github.com/gajus/babel-plugin-transform-function-composition')
)({
name: 'babel-plugin-transform-function-composition'
})
You can use ::
to achieve an equivalent composition:
import {
assocPath
} from 'ramda';
({
name: 'babel-plugin-transform-function-composition'
})
::assocPath(['repository', 'type'], 'git')
::assocPath(['repository', 'url'], 'https://github.com/gajus/babel-plugin-transform-function-composition');
In both cases, the result of the operation is:
{
name: 'babel-plugin-transform-function-composition',
repository: {
type: 'git',
url: 'https://github.com/gajus/babel-plugin-transform-function-composition'
}
}