Related
I stumbled upon this javascript statement:
const pipe = (...fns) => x => fns.reduce((y, f) => f(y), x);
I don't understand the expression f(y), x. With some experimenting I found out that this is working too: f(y(x)). It gives the exact same result (for my example at least and is much more understandable to me).
const pipe1 = (...fns) => x => fns.reduce((y, f) => f(y), x);
const pipe2 = (...fns) => x => fns.reduce((y, f) => f(y(x)));
const addThree = x => x + 3;
const addTwo = x => x + 2;
let x1 = pipe1(addTwo, addThree)(2); //x1 is seven
let x2 = pipe2(addTwo, addThree)(2); //x2 is seven
Then I thought that this is some syntax sugar for x,y for x(y) and tried this:
let z = n => addThree, n; //addThree(n)? no, that does not work!
I need some light on the expression f(y), x). Yes I read some stackoverflow articles that the expression is evaluated form left to right and the last is returned. It just makes no sense to me in this example.
fns.reduce((y, f) => f(y), x)
If you format it, it might make more sense.
fns.reduce(
(y, f) => f(y),
x
)
So (y, f) => f(y) is the first parameter to reduce (the reducer function), and x is the 2nd parameter to reduce, which is the initial value.
In conclusion, you were thrown off by the lack of grouping with the arrow function. :)
"Value-X" is going to be the x variable, passed as the 2nd parameter to the reduce function.
const pipe = (...fns) => x => fns.reduce((y, f) => f(y), x);
const foo = pipe(func1, func2, func3);
foo("Value-X");
The expression can be rewritten as this, if it helps to clarify things:
function pipe(...fns) {
return function (x) {
function chain(y, f) {
// y = previous return value
// If this is the first time the function is called, y = x
return f(y);
}
return fns.reduce(chain, x);
}
}
I am learning function programming in JavaScript, currently I have the following code.
I would like to combine this two functions in another function which alllow an user to pass a value in and having the result equal to the value passed plus 10 multiply 3 using the following functions.
Pseudo code example:
const myFormulat= add(10).multiply(3);
How can I write this function using only vanilla JS ES6?
function add(x){
return function(y){
return y + x;
};
}
function multiply(x){
return function(y){
return y * x;
};
}
// my calculation
// get x add 10 and after multiply by 3
Bear traps and landmines
This answer exists solely to demonstrate why this is not such a great idea – complexity is thru the roof with basically no gain. Note we must tell our function when to end, so i've added a special function call so our expressions will look like this
.add(3).mult(4).call(x)
// where x is the input for the entire function chain
One last change is our library of functions add, mult, et al must be wrapped in some scope that limits the reach of our proxy. This scope tells us exactly where the functions we wish to chain exist.
Oh and if the title of this section wasn't a warning enough, we use a Proxy too.
// helpers
const identity = x => x
const comp = f => g => x => f(g(x))
// magic wand
const using = scope => {
let acc = identity
let p = new Proxy({
call: x => acc(x),
}, {
get: (target, name) => {
if (name in target)
return target[name]
else if (name in scope)
return x => {
acc = comp (scope[name](x)) (acc)
return p
}
else
throw Error(`${f} is not undefined in ${scope}`)
}
})
return p
}
// your functions wrapped in a scope
const math = {
add: x => y => x + y,
mult: x => y => x * y
}
// chain it up
const main = using(math).add(3).mult(4).add(5).mult(6).call
console.log(main(2))
// (((2 + 3) * 4) + 5) * 6
// ((5 * 4) + 5) * 6
// (20 + 5) * 6
// 25 * 6
// 150
Function composition
But seriously, don't do that. Pushing everything through the . operator is unnatural given your starting point and you should be looking for more effective means to combine functions.
We can effectively do the same thing using a slightly different notation – the biggest difference here is complexity is almost zero
const compose = (f,...fs) => x =>
f === undefined ? x : compose (...fs) (f(x))
const add = x => y => x + y
const mult = x => y => x * y
const main = compose (add(3), mult(4), add(5), mult(6))
console.log(main(2)) // => 150
Functors
Maybe you don't like traditional function composition, and that's fine, because we have yet another way to tackle this problem using Functors – simply put, a Functor is a container with a map function.
Below we have a Box function which puts values in our container. The map function accepts a function and creates a new Box with the return value of the user-specified function. Lastly, we have a fold function which allows us to take our value out of the box
Again, it changes up the way we write the code a little bit, but the reduction is complexity is tremendous (compared to the Proxy example)
const Box = x => ({
map: f => Box(f(x)),
fold: f => f(x)
})
const add = x => y => x + y
const mult = x => y => x * y
const main = Box(2).map(add(3)).map(mult(4)).map(add(5)).map(mult(6)).fold
main(console.log) // 150
See: http://scott.sauyet.com/Javascript/Talk/Compose/2013-05-22/
function add(x){
return function(y){
return y + x;
};
}
function multiply(x){
return function(y){
return y * x;
};
}
Function.prototype.compose = function(g) {
var fn = this;
return function() {
return fn.call(this, g.apply(this, arguments));
};
};
var f = multiply(3).compose(add(10));
console.log(f(5));
If i understand you correctly you are trying to figure out function chaining in JavaScript
Function Chaining or Method chaining is a common pattern in JS world.
one of the methods in which you can achieve chaining is by creating a class and returning this operator or current object reference back
You can find interesting tutorial regarding this in following URL
https://www.bennadel.com/blog/2798-using-method-chaining-with-the-revealing-module-pattern-in-javascript.htm
The typical way to loop x times in JavaScript is:
for (var i = 0; i < x; i++)
doStuff(i);
But I don't want to use the ++ operator or have any mutable variables at all. So is there a way, in ES6, to loop x times another way? I love Ruby's mechanism:
x.times do |i|
do_stuff(i)
end
Anything similar in JavaScript/ES6? I could kind of cheat and make my own generator:
function* times(x) {
for (var i = 0; i < x; i++)
yield i;
}
for (var i of times(5)) {
console.log(i);
}
Of course I'm still using i++. At least it's out of sight :), but I'm hoping there's a better mechanism in ES6.
Using the ES2015 Spread operator:
[...Array(n)].map()
const res = [...Array(10)].map((_, i) => {
return i * 10;
});
// as a one liner
const res = [...Array(10)].map((_, i) => i * 10);
Or if you don't need the result:
[...Array(10)].forEach((_, i) => {
console.log(i);
});
// as a one liner
[...Array(10)].forEach((_, i) => console.log(i));
Or using the ES2015 Array.from operator:
Array.from(...)
const res = Array.from(Array(10)).map((_, i) => {
return i * 10;
});
// as a one liner
const res = Array.from(Array(10)).map((_, i) => i * 10);
Note that if you just need a string repeated you can use String.prototype.repeat.
console.log("0".repeat(10))
// 0000000000
OK!
The code below is written using ES6 syntaxes but could just as easily be written in ES5 or even less. ES6 is not a requirement to create a "mechanism to loop x times"
If you don't need the iterator in the callback, this is the most simple implementation
const times = x => f => {
if (x > 0) {
f()
times (x - 1) (f)
}
}
// use it
times (3) (() => console.log('hi'))
// or define intermediate functions for reuse
let twice = times (2)
// twice the power !
twice (() => console.log('double vision'))
If you do need the iterator, you can use a named inner function with a counter parameter to iterate for you
const times = n => f => {
let iter = i => {
if (i === n) return
f (i)
iter (i + 1)
}
return iter (0)
}
times (3) (i => console.log(i, 'hi'))
Stop reading here if you don't like learning more things ...
But something should feel off about those...
single branch if statements are ugly — what happens on the other branch ?
multiple statements/expressions in the function bodies — are procedure concerns being mixed ?
implicitly returned undefined — indication of impure, side-effecting function
"Isn't there a better way ?"
There is. Let's first revisit our initial implementation
// times :: Int -> (void -> void) -> void
const times = x => f => {
if (x > 0) {
f() // has to be side-effecting function
times (x - 1) (f)
}
}
Sure, it's simple, but notice how we just call f() and don't do anything with it. This really limits the type of function we can repeat multiple times. Even if we have the iterator available, f(i) isn't much more versatile.
What if we start with a better kind of function repetition procedure ? Maybe something that makes better use of input and output.
Generic function repetition
// repeat :: forall a. Int -> (a -> a) -> a -> a
const repeat = n => f => x => {
if (n > 0)
return repeat (n - 1) (f) (f (x))
else
return x
}
// power :: Int -> Int -> Int
const power = base => exp => {
// repeat <exp> times, <base> * <x>, starting with 1
return repeat (exp) (x => base * x) (1)
}
console.log(power (2) (8))
// => 256
Above, we defined a generic repeat function which takes an additional input which is used to start the repeated application of a single function.
// repeat 3 times, the function f, starting with x ...
var result = repeat (3) (f) (x)
// is the same as ...
var result = f(f(f(x)))
Implementing times with repeat
Well this is easy now; almost all of the work is already done.
// repeat :: forall a. Int -> (a -> a) -> a -> a
const repeat = n => f => x => {
if (n > 0)
return repeat (n - 1) (f) (f (x))
else
return x
}
// times :: Int -> (Int -> Int) -> Int
const times = n=> f=>
repeat (n) (i => (f(i), i + 1)) (0)
// use it
times (3) (i => console.log(i, 'hi'))
Since our function takes i as an input and returns i + 1, this effectively works as our iterator which we pass to f each time.
We've fixed our bullet list of issues too
No more ugly single branch if statements
Single-expression bodies indicate nicely separated concerns
No more useless, implicitly returned undefined
JavaScript comma operator, the
In case you're having trouble seeing how the last example is working, it depends on your awareness of one of JavaScript's oldest battle axes; the comma operator – in short, it evaluates expressions from left to right and returns the value of the last evaluated expression
(expr1 :: a, expr2 :: b, expr3 :: c) :: c
In our above example, I'm using
(i => (f(i), i + 1))
which is just a succinct way of writing
(i => { f(i); return i + 1 })
Tail Call Optimisation
As sexy as the recursive implementations are, at this point it would be irresponsible for me to recommend them given that no JavaScript VM I can think of supports proper tail call elimination – babel used to transpile it, but it's been in "broken; will reimplement" status for well over a year.
repeat (1e6) (someFunc) (x)
// => RangeError: Maximum call stack size exceeded
As such, we should revisit our implementation of repeat to make it stack-safe.
The code below does use mutable variables n and x but note that all mutations are localized to the repeat function – no state changes (mutations) are visible from outside of the function
// repeat :: Int -> (a -> a) -> (a -> a)
const repeat = n => f => x =>
{
let m = 0, acc = x
while (m < n)
(m = m + 1, acc = f (acc))
return acc
}
// inc :: Int -> Int
const inc = x =>
x + 1
console.log (repeat (1e8) (inc) (0))
// 100000000
This is going to have a lot of you saying "but that's not functional !" – I know, just relax. We can implement a Clojure-style loop/recur interface for constant-space looping using pure expressions; none of that while stuff.
Here we abstract while away with our loop function – it looks for a special recur type to keep the loop running. When a non-recur type is encountered, the loop is finished and the result of the computation is returned
const recur = (...args) =>
({ type: recur, args })
const loop = f =>
{
let acc = f ()
while (acc.type === recur)
acc = f (...acc.args)
return acc
}
const repeat = $n => f => x =>
loop ((n = $n, acc = x) =>
n === 0
? acc
: recur (n - 1, f (acc)))
const inc = x =>
x + 1
const fibonacci = $n =>
loop ((n = $n, a = 0, b = 1) =>
n === 0
? a
: recur (n - 1, b, a + b))
console.log (repeat (1e7) (inc) (0)) // 10000000
console.log (fibonacci (100)) // 354224848179262000000
for (let i of Array(100).keys()) {
console.log(i)
}
Here is another good alternative:
Array.from({ length: 3}).map(...);
Preferably, as #Dave Morse pointed out in the comments, you can also get rid of the map call, by using the second parameter of the Array.from function like so:
Array.from({ length: 3 }, () => (...))
I think the best solution is to use let:
for (let i=0; i<100; i++) …
That will create a new (mutable) i variable for each body evaluation and assures that the i is only changed in the increment expression in that loop syntax, not from anywhere else.
I could kind of cheat and make my own generator. At least i++ is out of sight :)
That should be enough, imo. Even in pure languages, all operations (or at least, their interpreters) are built from primitives that use mutation. As long as it is properly scoped, I cannot see what is wrong with that.
You should be fine with
function* times(n) {
for (let i = 0; i < n; i++)
yield i;
}
for (const i of times(5)) {
console.log(i);
}
But I don't want to use the ++ operator or have any mutable variables at all.
Then your only choice is to use recursion. You can define that generator function without a mutable i as well:
function* range(i, n) {
if (i >= n) return;
yield i;
return yield* range(i+1, n);
}
times = (n) => range(0, n);
But that seems overkill to me and might have performance problems (as tail call elimination is not available for return yield*).
I think it is pretty simple:
[...Array(3).keys()]
or
Array(3).fill()
const times = 4;
new Array(times).fill().map(() => console.log('test'));
This snippet will console.log test 4 times.
Answer: 09 December 2015
Personally, I found the accepted answer both concise (good) and terse (bad). Appreciate this statement might be subjective, so please read this answer and see if you agree or disagree
The example given in the question was something like Ruby's:
x.times do |i|
do_stuff(i)
end
Expressing this in JS using below would permit:
times(x)(doStuff(i));
Here is the code:
let times = (n) => {
return (f) => {
Array(n).fill().map((_, i) => f(i));
};
};
That's it!
Simple example usage:
let cheer = () => console.log('Hip hip hooray!');
times(3)(cheer);
//Hip hip hooray!
//Hip hip hooray!
//Hip hip hooray!
Alternatively, following the examples of the accepted answer:
let doStuff = (i) => console.log(i, ' hi'),
once = times(1),
twice = times(2),
thrice = times(3);
once(doStuff);
//0 ' hi'
twice(doStuff);
//0 ' hi'
//1 ' hi'
thrice(doStuff);
//0 ' hi'
//1 ' hi'
//2 ' hi'
Side note - Defining a range function
A similar / related question, that uses fundamentally very similar code constructs, might be is there a convenient Range function in (core) JavaScript, something similar to underscore's range function.
Create an array with n numbers, starting from x
Underscore
_.range(x, x + n)
ES2015
Couple of alternatives:
Array(n).fill().map((_, i) => x + i)
Array.from(Array(n), (_, i) => x + i)
Demo using n = 10, x = 1:
> Array(10).fill().map((_, i) => i + 1)
// [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
> Array.from(Array(10), (_, i) => i + 1)
// [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
In a quick test I ran, with each of the above running a million times each using our solution and doStuff function, the former approach (Array(n).fill()) proved slightly faster.
I am late to the party, but since this question turns up often in search results, I would just like to add a solution that I consider to be the best in terms of readability while not being long (which is ideal for any codebase IMO). It mutates, but I'd make that tradeoff for KISS principles.
let times = 5
while( times-- )
console.log(times)
// logs 4, 3, 2, 1, 0
Array(100).fill().map((_,i)=> console.log(i) );
This version satisifies the OP's requirement for immutability. Also consider using reduce instead of map depending on your use case.
This is also an option if you don't mind a little mutation in your prototype.
Number.prototype.times = function(f) {
return Array(this.valueOf()).fill().map((_,i)=>f(i));
};
Now we can do this
((3).times(i=>console.log(i)));
+1 to arcseldon for the .fill suggestion.
Not something I would teach (or ever use in my code), but here's a codegolf-worthy solution without mutating a variable, no need for ES6:
Array.apply(null, {length: 10}).forEach(function(_, i){
doStuff(i);
})
More of an interesting proof-of-concept thing than a useful answer, really.
If you're willing to use a library, there's also lodash _.times or underscore _.times:
_.times(x, i => {
return doStuff(i)
})
Note this returns an array of the results, so it's really more like this ruby:
x.times.map { |i|
doStuff(i)
}
Afaik, there is no mechanism in ES6 similar to Ruby's times method. But you can avoid mutation by using recursion:
let times = (i, cb, l = i) => {
if (i === 0) return;
cb(l - i);
times(i - 1, cb, l);
}
times(5, i => doStuff(i));
Demo: http://jsbin.com/koyecovano/1/edit?js,console
In the functional paradigm repeat is usually an infinite recursive function. To use it we need either lazy evaluation or continuation passing style.
Lazy evaluated function repetition
const repeat = f => x => [x, () => repeat(f) (f(x))];
const take = n => ([x, f]) => n === 0 ? x : take(n - 1) (f());
console.log(
take(8) (repeat(x => x * 2) (1)) // 256
);
I use a thunk (a function without arguments) to achieve lazy evaluation in Javascript.
Function repetition with continuation passing style
const repeat = f => x => [x, k => k(repeat(f) (f(x)))];
const take = n => ([x, k]) => n === 0 ? x : k(take(n - 1));
console.log(
take(8) (repeat(x => x * 2) (1)) // 256
);
CPS is a little scary at first. However, it always follows the same pattern: The last argument is the continuation (a function), which invokes its own body: k => k(...). Please note that CPS turns the application inside out, i.e. take(8) (repeat...) becomes k(take(8)) (...) where k is the partially applied repeat.
Conclusion
By separating the repetition (repeat) from the termination condition (take) we gain flexibility - separation of concerns up to its bitter end :D
Advantages of this solution
Simplest to read / use (imo)
Return value can be used as a sum, or just ignored
Plain es6 version, also link to TypeScript version of the code
Disadvantages
- Mutation. Being internal only I don't care, maybe some others will not either.
Examples and Code
times(5, 3) // 15 (3+3+3+3+3)
times(5, (i) => Math.pow(2,i) ) // 31 (1+2+4+8+16)
times(5, '<br/>') // <br/><br/><br/><br/><br/>
times(3, (i, count) => { // name[0], name[1], name[2]
let n = 'name[' + i + ']'
if (i < count-1)
n += ', '
return n
})
function times(count, callbackOrScalar) {
let type = typeof callbackOrScalar
let sum
if (type === 'number') sum = 0
else if (type === 'string') sum = ''
for (let j = 0; j < count; j++) {
if (type === 'function') {
const callback = callbackOrScalar
const result = callback(j, count)
if (typeof result === 'number' || typeof result === 'string')
sum = sum === undefined ? result : sum + result
}
else if (type === 'number' || type === 'string') {
const scalar = callbackOrScalar
sum = sum === undefined ? scalar : sum + scalar
}
}
return sum
}
TypeScipt version
https://codepen.io/whitneyland/pen/aVjaaE?editors=0011
The simplest way I can think of for creating list/array within range
Array.from(Array(max-min+1), (_, index) => index+min)
I have another alternative
[...Array(30).keys()]
addressing the functional aspect:
function times(n, f) {
var _f = function (f) {
var i;
for (i = 0; i < n; i++) {
f(i);
}
};
return typeof f === 'function' && _f(f) || _f;
}
times(6)(function (v) {
console.log('in parts: ' + v);
});
times(6, function (v) {
console.log('complete: ' + v);
});
Generators? Recursion? Why so much hatin' on mutatin'? ;-)
If it is acceptable as long as we "hide" it, then just accept the use of a unary operator and we can keep things simple:
Number.prototype.times = function(f) { let n=0 ; while(this.valueOf() > n) f(n++) }
Just like in ruby:
> (3).times(console.log)
0
1
2
I wrapped #Tieme s answer with a helper function.
In TypeScript:
export const mapN = <T = any[]>(count: number, fn: (...args: any[]) => T): T[] => [...Array(count)].map((_, i) => fn())
Now you can run:
const arr: string[] = mapN(3, () => 'something')
// returns ['something', 'something', 'something']
I made this:
function repeat(func, times) {
for (var i=0; i<times; i++) {
func(i);
}
}
Usage:
repeat(function(i) {
console.log("Hello, World! - "+i);
}, 5)
/*
Returns:
Hello, World! - 0
Hello, World! - 1
Hello, World! - 2
Hello, World! - 3
Hello, World! - 4
*/
The i variable returns the amount of times it has looped - useful if you need to preload an x amount of images.
I am just going to put this here. If you are looking for a compact function without using Arrays and you have no issue with mutability/immutability :
var g =x=>{/*your code goes here*/x-1>0?g(x-1):null};
For me, this is the easiest answer to understand for many levels of developers
const times = (n, callback) => {
while (n) {
callback();
n--;
}
}
times(10, ()=> console.log('hello'))
It seems to me that the most correct answer (which is debatable) to this question is buried in a comment by Sasha Kondrashov and is also the most concise, using just two characters: "no". There is no functional alternative to a for-loop as nice as the syntax that Ruby has. We might want there to be one, but there just isn't.
It is not explicitly stated in the question, but I would argue any solution to the problem of 'looping N times' should not allocate memory, at least not proportional to N. That criterium would rule out most of the answers that are 'native to javascript'.
Other answers show implementations like the one in Ruby, which is fine, except that the question explicitly asks for a native javascript solution. And there is already a very decent hand-rolled solution in the question, arguably one of the most readable of all.
I'm learning functional programming and I wonder if there is a way to "combine" functions like this:
function triple(x) {
return x * 3;
}
function plusOne(x) {
return x + 1;
}
function isZero(x) {
return x === 0;
}
combine(1); //1
combine(triple)(triple)(plusOne)(1); // 10
combine(plusOne)(triple)(isZero)(-1); // true
If the para is a function, it "combines" the function into itself, and if not it will return the final result.
Thanks!
heritage
This is a concept from maths called function composition.
f(x) = y
g(y) = z
g(f(x)) = z
(g•f)(x) = z
That last line is read "g of f of x equals z". What's great about composed functions is the elimination of points. Notice in g(f(x)) = z we take an x input and get a z output. This skips the intermediate point, y.
Composition is a great way to create higher-order functions and keep your code sparkly clean. It's plain to see why we'd want this in our Javascript programs.
comp
JavaScript is a multi-paradigm language with rich support for functions. We can create a simple comp function, which combines two input functions, g and f, and results in a new function -
function triple(x) {
return x * 3
}
function plusOne(x) {
return x + 1
}
function comp(g, f) {
return function(x) {
return g(f(x)) // "g of f of x"
}
}
const myfunc =
comp(triple, plusOne)
console.log(myfunc(1))
Evaluation
triple(plusOne(1))
triple(2)
6
compose
Just as the question suggests, it's likely we will want to combine more than two functions. Below we write compose which takes all of the input functions and reduces them using our simple comp from above. If no functions are given, we return the empty function, identity -
const triple = (x) =>
x * 3
const plusOne = (x) =>
x + 1
const comp = (g, f) =>
x => g(f(x)) // "g of f of x"
const identity = (x) =>
x
const compose = (...all) =>
all.reduce(comp, identity)
const myfunc =
compose(triple, triple, plusOne) // any amount of funcs
console.log(myfunc(1))
Evaluation
triple(triple(plusOne(1)))
triple(triple(2))
triple(6)
18
pipe
You can be as creative as you like. Below, we write pipe which allows our programs to read in a comfortable left-to-right direction -
const triple = (x) =>
x * 3
const plusOne = (x) =>
x + 1
const pipe = x =>
f => pipe(f(x))
pipe(1)(plusOne)(triple)(triple)(console.log) // 18
pipe(3)(triple)(plusOne)(triple)(plusOne)(console.log) // 31
Evaluation of expression one -
f => pipe(f(1))
pipe(plusOne(1))
f => pipe(f(2))
pipe(triple(2))
f => pipe(f(6))
pipe(triple(6))
f => pipe(f(18))
pipe(console.log(18))
18
and expression two -
f => pipe(f(3))
pipe(triple(3))
f => pipe(f(9))
pipe(plusOne(9))
f => pipe(f(10))
pipe(triple(10))
f => pipe(f(30))
pipe(plusOne(31))
f => pipe(f(31))
pipe(console.log(31))
31
related techniques
Curried functions and partial application are concepts that gel with function composition. pipe above is introduced in another Q&A as $ and demonstrated again here -
const $ = x => // "pipe", or whatever name you pick
k => $ (k (x))
const add = x => y => // curried add
x + y
const mult = x => y => // curried mult
x * y
$ (1) // 1
(add (2)) // + 2 = 3
(mult (6)) // * 6 = 18
(console.log) // 18
$ (7) // 7
(add (1)) // + 1 = 8
(mult (8)) // * 8 = 64
(mult (2)) // * 2 = 128
(mult (2)) // * 2 = 256
(console.log) // 256
function triple(x) {
return x * 3;
}
function plusOne(x) {
return x + 1;
}
function isZero(x) {
return x === 0;
}
var combine = function (v) {
var fn = [];
function _f(v) {
if (typeof v === 'function') {
fn.push(v);
return _f;
} else {
return fn.reduce(function (x, f) { return f(x); }, v);
}
}
return _f(v);
};
var a, b;
console.log(combine(1)); //1
console.log(combine(triple)(triple)(plusOne)(1)); // 10
console.log(combine(plusOne)(triple)(isZero)(-1)); // true
console.log(a = combine(plusOne)); // function ...
console.log(b = a(triple)); // function ...
console.log(b(5)); // 18
console.log(combine(triple)(plusOne)(triple)(plusOne)(triple)(plusOne)(1)); // 40
// #naomik's examples
var f = combine(triple);
var g = combine(triple)(triple);
console.log(f(1)); // 3
console.log(g(1)); // 9 (not 6 as you stated)
Function composition has already been detailed in other answers, mostly https://stackoverflow.com/a/30198265/4099454, so my 2 cents are straight onto answering your latest question:
If the para is a function, it "combines" the function into itself, and if not it will return the final result. Thanks!
const chain = (g, f = x => x) =>
typeof g === 'function'
? (y) => chain(y, (x) => g(f(x)))
: f(g);
// ====
const triple = x => x * 3;
const inc = x => x + 1;
const isZero = x => x === 0;
console.log(
chain(inc)(triple)(isZero)(-1),
);
It is also possible to build a complex Functionality by Composing Simple Functions in JavaScript.In a sense, the composition is the nesting of functions, passing the result of one in as the input into the next. But rather than creating an indecipherable amount of nesting, we'll create a higher-order function, compose(), that takes all of the functions we want to combine, and returns us a new function to use in our app.
function triple(x) {
return x * 3;
}
function plusOne(x) {
return x + 1;
}
function isZero(x) {
return x === 0;
}
const compose = (...fns) => x =>
fns.reduce((acc, cur) => {
return cur(acc);
}, x);
const withCompose = compose(triple, triple, isZero);
console.log(withCompose(1));
You can simply call the function on the return values themselves, for example:
plusOne(triple(triple(1))) // 10
isZero(triple(plusOne(-1))) // true
I wrote a simple curry function in JavaScript which works correctly for most cases:
const curry = (f, ...a) => a.length < f.length
? (...b) => curry(f, ...a, ...b)
: f(...a);
const add = curry((a, b, c) => a + b + c);
const add2 = add(2);
const add5 = add2(3);
console.log(add5(5));
However, it doesn't work for the following case:
// length :: [a] -> Number
const length = a => a.length;
// filter :: (a -> Bool) -> [a] -> [a]
const filter = curry((f, a) => a.filter(f));
// compose :: (b -> c) -> (a -> b) -> a -> c
const compose = curry((f, g, x) => f(g(x)));
// countWhere :: (a -> Bool) -> [a] -> Number
const countWhere = compose(compose(length), filter);
According to the following question countWhere is defined as (length .) . filter:
What does (f .) . g mean in Haskell?
Hence I should be able to use countWhere as follows:
const odd = n => n % 2 === 1;
countWhere(odd, [1,2,3,4,5]);
However, instead of returning 3 (the length of the array [1,3,5]), it returns a function. What am I doing wrong?
#Aadit,
I'm posting this because you shared a comment on my answer to To “combine” functions in javascript in a functional way? I didn't specifically cover currying in that post because it's a very contentious topic and not really a can of worms I wanted to open there.
I'd be wary using the phrasing "how to correctly curry" when you seem to be adding your own sugar and conveniences into your implementation.
Anyway, all of that aside, I truly don't intend for this to be an argumentative/combative post. I'd like to be able to have an open, friendly discussion about currying in JavaScript while emphasizing some of the differences between our approaches.
Without further ado...
To clarify:
Given f is a function and f.length is n. Let curry(f) be g. We call g with m arguments. What should happen? You say:
If m === 0 then just return g.
If m < n then partially apply f to the m new arguments, and return a new curried function which accepts the remaining n - m arguments.
If m === n then apply f to the m arguments. If the result is a function then curry the result. Finally, return the result.
If m > n then apply f to the first n arguments. If the result is a function then curry the result. Finally, apply the result to the remaining m - n arguments and return the new result.
Let's see a code example of what #Aadit M Shah's code actually does
var add = curry(function(x, y) {
return function(a, b) {
return x + y + a + b;
}
});
var z = add(1, 2, 3);
console.log(z(4)); // 10
There are two things happening here:
You're attempting to support calling curried functions with variadic arguments.
You're automatically currying returned functions
I don't believe there's a lot of room for debate here, but people seem to miss what currying actually is
via: Wikipedia
In mathematics and computer science, currying is the technique of translating the evaluation of a function that takes multiple arguments (or a tuple of arguments) into evaluating a sequence of functions, each with a single argument...
I'm bolding that last bit, because it's so important; each function in the sequence only takes a single argument; not variadic (0, 1, or more) arguments like you suggest.
You mention haskell in your post, too, so I assume you know that Haskell has no such thing as functions that take more than one argument. (Note: a function that takes a tuple is still just a function that takes one argument, a single tuple). The reasons for this are profound and afford you a flexibility in expressiveness not afforded to you by functions with variadic arguments.
So let's re-ask that original question: What should happen?
Well, it's simple when each function only accepts 1 argument. At any time, if more than 1 argument is given, they're just dropped.
function id(x) {
return x;
}
What happens when we call id(1,2,3,4)? Of course we only get the 1 back and 2,3,4 are completely disregarded. This is:
how JavaScript works
how Wikipedia says currying should work
how we should implement our own curry solution
Before we go further, I'm going to use ES6-style arrow functions but I will also include the ES5 equivalent at the bottom of this post. (Probably later tonight.)
another currying technique
In this approach, we write a curry function that continuously returns single-parameter functions until all arguments have been specified
As a result of this implementation we have 6 multi-purpose functions.
// no nonsense curry
const curry = f => {
const aux = (n, xs) =>
n === 0 ? f (...xs) : x => aux (n - 1, [...xs, x])
return aux (f.length, [])
}
// demo
let sum3 = curry(function(x,y,z) {
return x + y + z;
});
console.log (sum3 (3) (5) (-1)); // 7
OK, so we've seen a curry technique that is implemented using a simple auxiliary loop. It has no dependencies and a declarative definition that is under 5 lines of code. It allows functions to be partially applied, 1 argument at a time, just as a curried function is supposed to work.
No magic, no unforeseen auto-currying, no other unforeseen consequences.
But what really is the point of currying anyway?
Well, as it turns out, I don't really curry functions that I write. As you can see below, I generally define all of my reusable functions in curried form. So really, you only need curry when you want to interface with some functions that you don't have control over, perhaps coming from a lib or something; some of which might have variadic interfaces!
I present curryN
// the more versatile, curryN
const curryN = n => f => {
const aux = (n, xs) =>
n === 0 ? f (...xs) : x => aux (n - 1, [...xs, x])
return aux (n, [])
};
// curry derived from curryN
const curry = f => curryN (f.length) (f);
// some caveman function
let sumN = function() {
return [].slice.call(arguments).reduce(function(a, b) {
return a + b;
});
};
// curry a fixed number of arguments
let g = curryN (5) (sumN);
console.log (g (1) (2) (3) (4) (5)); // 15
To curry or not to curry? That is the question
We'll write some examples where our functions are all in curried form. Functions will be kept extremely simple. Each with 1 parameter, and each with a single return expression.
// composing two functions
const comp = f => g => x => f (g (x))
const mod = y => x => x % y
const eq = y => x => x === y
const odd = comp (eq (1)) (mod (2))
console.log (odd(1)) // true
console.log (odd(2)) // false
Your countWhere function
// comp :: (b -> c) -> (a -> b) -> (a -> c)
const comp = f => g => x =>
f(g(x))
// mod :: Int -> Int -> Int
const mod = x => y =>
y % x
// type Comparable = Number | String
// eq :: Comparable -> Comparable -> Boolean
const eq = x => y =>
y === x
// odd :: Int -> Boolean
const odd =
comp (eq(1)) (mod(2))
// reduce :: (b -> a -> b) -> b -> ([a]) -> b
const reduce = f => y => ([x,...xs]) =>
x === undefined ? y : reduce (f) (f(y)(x)) (xs)
// filter :: (a -> Boolean) -> [a] -> [a]
const filter = f =>
reduce (acc => x => f (x) ? [...acc,x] : acc) ([])
// length :: [a] -> Int
const length = x =>
x.length
// countWhere :: (a -> Boolean) -> [a] -> Int
const countWhere = f =>
comp (length) (filter(f));
console.log (countWhere (odd) ([1,2,3,4,5]))
// 3
Remarks
So to curry or not to curry?
// to curry
const add3 = curry((a, b, c) =>
a + b + c
)
// not to curry
const add3 = a => b => c =>
a + b + c
With ES6 arrow functions being the go-to choice for today's JavaScripter, I think the choice to manually curry your functions is a no-brainer. It's actually shorter and has less overhead to just write it out in curried form.
That said, you're still going to be interfacing with libs that do not offer curried forms of the functions they expose. For this situation, I'd recommend
curry and curryN (defined above)
partial (as defined here)
#Iven,
Your curryN implementation is very nice. This section exists solely for you.
const U = f=> f (f)
const Y = U (h=> f=> f(x=> h (h) (f) (x)))
const curryN = Y (h=> xs=> n=> f=>
n === 0 ? f(...xs) : x=> h ([...xs, x]) (n-1) (f)
) ([])
const curry = f=> curryN (f.length) (f)
const add3 = curry ((x,y,z)=> x + y + z)
console .log (add3 (3) (6) (9))
The problem with your curry function (and for most curry functions that people write in JavaScript) is that it doesn't handle extra arguments correctly.
What curry does
Suppose f is a function and f.length is n. Let curry(f) be g. We call g with m arguments. What should happen?
If m === 0 then just return g.
If m < n then partially apply f to the m new arguments, and return a new curried function which accepts the remaining n - m arguments.
Otherwise apply f to the m arguments and return the result.
This is what most curry functions do, and this is wrong. The first two cases are right, but the third case is wrong. Instead, it should be:
If m === 0 then just return g.
If m < n then partially apply f to the m new arguments, and return a new curried function which accepts the remaining n - m arguments.
If m === n then apply f to the m arguments. If the result is a function then curry the result. Finally, return the result.
If m > n then apply f to the first n arguments. If the result is a function then curry the result. Finally, apply the result to the remaining m - n arguments and return the new result.
The problem with most curry functions
Consider the following code:
const countWhere = compose(compose(length), filter);
countWhere(odd, [1,2,3,4,5]);
If we use the incorrect curry functions, then this is equivalent to:
compose(compose(length), filter, odd, [1,2,3,4,5]);
However, compose only accepts three arguments. The last argument is dropped:
const compose = curry((f, g, x) =>f(g(x)));
Hence, the above expression evaluates to:
compose(length)(filter(odd));
This further evaluates to:
compose(length, filter(odd));
The compose function expects one more argument which is why it returns a function instead of returning 3. To get the correct output you need to write:
countWhere(odd)([1,2,3,4,5]);
This is the reason why most curry functions are wrong.
The solution using the correct curry function
Consider the following code again:
const countWhere = compose(compose(length), filter);
countWhere(odd, [1,2,3,4,5]);
If we use the correct curry function, then this is equivalent to:
compose(compose(length), filter, odd)([1,2,3,4,5]);
Which evaluates to:
compose(length)(filter(odd))([1,2,3,4,5]);
Which further evaluates to (skipping an intermediate step):
compose(length, filter(odd), [1,2,3,4,5]);
Which results in:
length(filter(odd, [1,2,3,4,5]));
Producing the correct result 3.
The implementation of the correct curry function
Implementing the correct curry function in ES6 is straightforward:
const curry = (f, ...a) => {
const n = f.length, m = a.length;
if (n === 0) return m > n ? f(...a) : f;
if (m === n) return autocurry(f(...a));
if (m < n) return (...b) => curry(f, ...a, ...b);
return curry(f(...a.slice(0, n)), ...a.slice(n));
};
const autocurry = (x) => typeof x === "function" ? curry(x) : x;
Note that if the length of the input function is 0 then it's assumed to be curried.
Implications of using the correct curry function
Using the correct curry function allows you to directly translate Haskell code into JavaScript. For example:
const id = curry(a => a);
const flip = curry((f, x, y) => f(y, x));
The id function is useful because it allows you to partially apply a non-curried function easily:
const add = (a, b) => a + b;
const add2 = id(add, 2);
The flip function is useful because it allows you to easily create right sections in JavaScript:
const sub = (a, b) => a - b;
const sub2 = flip(sub, 2); // equivalent to (x - 2)
It also means that you don't need hacks like this extended compose function:
What's a Good Name for this extended `compose` function?
You can simply write:
const project = compose(map, pick);
As mentioned in the question, if you want to compose length and filter then you use the (f .) . g pattern:
What does (f .) . g mean in Haskell?
Another solution is to create higher order compose functions:
const compose2 = compose(compose, compose);
const countWhere = compose2(length, fitler);
This is all possible because of the correct implementation of the curry function.
Extra food for thought
I usually use the following chain function when I want to compose a chain of functions:
const chain = compose((a, x) => {
var length = a.length;
while (length > 0) x = a[--length](x);
return x;
});
This allows you to write code like:
const inc = add(1);
const foo = chain([map(inc), filter(odd), take(5)]);
foo([1,2,3,4,5,6,7,8,9,10]); // [2,4,6]
Which is equivalent to the following Haskell code:
let foo = map (+1) . filter odd . take 5
foo [1,2,3,4,5,6,7,8,9,10]
It also allows you to write code like:
chain([map(inc), filter(odd), take(5)], [1,2,3,4,5,6,7,8,9,10]); // [2,4,6]
Which is equivalent to the following Haskell code:
map (+1) . filter odd . take 5 $ [1,2,3,4,5,6,7,8,9,10]
Hope that helps.
Apart from its mathematical definition
currying is the transformation of a function with n parameters into a sequence of n functions, which each accept a single parameter. The arity is thus transformed from n-ary to n * 1-ary
what impact has currying on programming? Abstraction over arity!
const comp = f => g => x => f(g(x));
const inc = x => x + 1;
const mul = y => x => x * y;
const sqr = x => mul(x)(x);
comp(sqr)(inc)(1); // 4
comp(mul)(inc)(1)(2); // 4
comp expects two functions f and g and a single arbitrary argument x. Consequently g must be an unary function (a function with exactly one formal parameter) and f too, since it is fed with the return value of g. It won't surprise anyone that comp(sqr)(inc)(1) works. sqr and inc are both unary.
But mul is obviously a binary function. How on earth is that going to work? Because currying abstracted the arity of mul. You can now probably imagine what a powerful feature currying is.
In ES2015 we can pre-curry our functions with arrow functions succinctly:
const map = (f, acc = []) => xs => xs.length > 0
? map(f, [...acc, f(xs[0])])(xs.slice(1))
: acc;
map(x => x + 1)([1,2,3]); // [2,3,4]
Nevertheless, we need a programmatic curry function for all functions out of our control. Since we learned that currying primarily means abstraction over arity, our implementation must not depend on Function.length:
const curryN = (n, acc = []) => f => x => n > 1
? curryN(n - 1, [...acc, x])(f)
: f(...acc, x);
const map = (f, xs) => xs.map(x => f(x));
curryN(2)(map)(x => x + 1)([1,2,3]); // [2,3,4]
Passing the arity explicitly to curryN has the nice side effect that we can curry variadic functions as well:
const sum = (...args) => args.reduce((acc, x) => acc + x, 0);
curryN(3)(sum)(1)(2)(3); // 6
One problem remains: Our curry solution can't deal with methods. OK, we can easily redefine methods that we need:
const concat = ys => xs => xs.concat(ys);
const append = x => concat([x]);
concat([4])([1,2,3]); // [1,2,3,4]
append([4])([1,2,3]); // [1,2,3,[4]]
An alternative is to adapt curryN in a manner that it can handle both multi-argument functions and methods:
const curryN = (n, acc = []) => f => x => n > 1
? curryN(n - 1, [...acc, x])(f)
: typeof f === "function"
? f(...acc, x)
: x[f](...acc);
curryN(2)("concat")(4)([1,2,3]); // [1,2,3,4]
I don't know if this is the correct way to curry functions (and methods) in Javascript though. It is rather one possible way.
EDIT:
naomik pointed out that by using a default value the internal API of the curry function is partially exposed. The achieved simplification of the curry function comes thus at the expense of its stability. To avoid API leaking we need a wrapper function. We can utilize the U combinator (similar to naomik's solution with Y):
const U = f => f(f);
const curryN = U(h => acc => n => f => x => n > 1
? h(h)([...acc, x])(n-1)(f)
: f(...acc, x))([]);
Drawback: The implementation is harder to read and has a performance penalty.
//---Currying refers to copying a function but with preset parameters
function multiply(a,b){return a*b};
var productOfSixNFiveSix = multiply.bind(this,6,5);
console.log(productOfSixNFive());
//The same can be done using apply() and call()
var productOfSixNFiveSix = multiply.call(this,6,5);
console.log(productOfSixNFive);
var productOfSixNFiveSix = multiply.apply(this,[6,5]);
console.log(productOfSixNFive);