My task is to write a higher order function for chaining together a list of unary functions.The first argument is an array, which holds the names of functions to be called.The second param is the value to be used with functions. Here is the code
function square (x) {return x * x;}
function add3 (x) {return x + 3;}
function chainer(a) {
return function (b) {
for(var i = 0; i < a.length; i++) {
return a[i](b)
}
}
}
console.log(chainer([square, add3])(4));
The desired output is 19 but it executes only the first function and prints out 16. I think I would need to compose these functions somehow but can`t wrap my head around it. Would I need to use apply() or call() methods to complete the task? I am new to functional programming.
Your problem is that return a[i](b) does only call the first function and immediately return its result. You will need to put the return after the loop:
for (var i = 0; i < a.length; i++) {
b = a[i](b)
}
return b
Alternatively, this is a great use case for reduce/fold (which you probably have encountered before function composition):
return function(b) {
return a.reduce(function(b, f) { return f(b) }, b)
};
or even
return a.reduce(compose, function id(x) { return x; });
Related
I'm trying to implement currying function:
function sum(a, b, c) {
console.log('SUM'+JSON.stringify(arguments))
return a + b + c;
}
var curry= function (func,...n) {
return function(...args2) {
//console.log('arg2s'+args2)
return func.apply(this,n.concat(args2));
};
}
curry(sum,1,2)(3) //SUM{"0":1,"1":2,"2":3}, O/P:6
Above gives correct output, but i am not getting the necessity to use apply.
So, if i change my function to below:
var curry= function (func,...n) {
return function(...args2) {
//console.log('arg2s'+args2)
return func(n.concat(args2));
};
}
curry(sum,1,2)(3) //SUM{"0":[1,2,3]} O/P:"1,2,3undefinedundefined"
I basically have two questions here:
Why is the implementation of curry not working when calling func directly?Why is the output such weird ?
2.How do i change my function in a way that i can call it as below and should return sum:
curry(1)(2)(3)/curry(1,2)(3)/curry(1,2,3) etc instead of the way i'm calling currently.
I could find some solutions on the web, but couldn't understand .
ex:
function curry(func) {
return function curriedFunc(...args) {
if (args.length >= func.length) {
return func.apply(this, args);
} else {
return function(...args1) {
return curriedFunc.apply(this, args.concat(args1));
}
}
};
}
Any help would be highly appreciated !!
Your func accepts three arguments: a, b, and c. When you do:
return func(n.concat(args2));
you're passing it one argument, an array. It's equivalent to:
const arr = n.concat(args2);
return func(arr);
Sounds like you'd want to spread the arguments into the call of func instead:
return func(...n, ...args2)
With spread syntax, each item from the iterable is put into a parameter. Eg, if the n array has one item, it gets set as the first argument passed to func, and if args2 has 2 items, the first gets set as the second argument passed, and the second gets set as the third argument passed.
function sum(a, b, c) {
console.log('SUM' + JSON.stringify(arguments))
return a + b + c;
}
var curry = function(func, ...n) {
return function(...args2) {
return func(...n, ...args2);
};
}
curry(sum, 1, 2)(3);
How do i change my function in a way that i can call it as below and should return sum: curry(1)(2)(3)/curry(1,2)(3)/curry(1,2,3) etc
Keep track of the total number of arguments passed in a closure created the first time the function is called. In the returned function, push all arguments to the array, and if the array's length is 3, return the sum, otherwise return the function again:
function sum(a, b, c) {
return a + b + c;
}
var curry = function(func, ...argsSoFar) {
const neededArgs = func.length;
const returnedFn = (...args) => {
argsSoFar.push(...args);
if (argsSoFar.length === neededArgs) {
return func(...argsSoFar);
} else {
return returnedFn;
}
};
return returnedFn;
}
console.log(
curry(sum, 1, 2)(3),
curry(sum)(1, 2)(3),
curry(sum)(1)(2, 3),
curry(sum)(1)(2)(3),
);
I recently started to learn javascript by myself and I am reading a book called "Eloquent JavaScript". The following code is a sample script in the book which confused me:
function greaterThan(n) {
return function(m) { return m > n; };
}
var greaterThan10 = greaterThan(10);
console.log(greaterThan10(11));
Can someone please explain the logic of the last two lines? Does the greaterThan10 contain a truth value or it is a function?
You define greaterThan10 on the second to last line:
var greaterThan10 = greaterThan(10);
Whatever the greaterThan function returns in this case is what greaterThan10 will evaluate to.
On line 2 we see that greaterThan will return the following function expression:
function(m) { return m > n; }
After replacing the variable n with the value you passed we get this:
function(m) { return m > 10; }
It can look a little confusing at first, but just keep in mind that functions are objects in JavaScript.
greaterThan(n) is a function that returns an anonymous function with the definition:
function(m) { return m > n; }
Therefore, when we call greaterThan(10) we expect it to return an object that is in fact a function:
function(m) { return m > 10; }
Later on we just assign that object/function to a variable, and call it like we would call any function.
In short, just imagine that we had:
var greaterThan10 = function(m) { return m > 10; };
I am learning JavaScript and got a bit confused with the following exercise. I did had to create a filter that would accept another functions as a sorting method. The thing that I cant understand a bit is how exactly the for loop passes the value to the x. Can you please explain?
function filter(arr, func) {
var result = [];
for (var i = 0; i < arr.length; i++) {
var value = arr[i];
if (func(value)) {
result.push(value);
}
}
return result
}
function inBetween(a, b) {
return function(x) {
return a <= x && x <= b;
}
}
function inArray(arr) {
return function(x) {
console.log(x)
return arr.indexOf(x) != -1;
}
}
var arr = [1, 2, 3, 4, 5, 6, 7];
alert(filter(arr, function(a) {
return a % 2 == 0
})); // 2,4,6
alert( filter(arr, inBetween(3, 6)) ); // 3,4,5,6
alert( filter(arr, inArray([1, 2, 10])) ); // 1,2
I'll take this line as example:
filter(arr, inArray([1, 2, 10])) );
inArray is called with arr = [1, 2, 10].
It returns the following (anonymous) function, for that particular arr:
function (x) {
return arr.indexOf(x) != -1;
}
So the original line now can be pictured as:
filter(arr, function (x) {
return [1, 2, 10].indexOf(x) != -1;
});
Now filter is called with func set to that anonymous function. The following code calls that function:
if (func(value)) {
result.push(value);
}
So when this func is called, this really means the above anonymous function is called, and the parameter x gets set to value at the moment of the call. It is just like with any other function call, the parameters of the function get the values of the arguments in the actual call.
Your filter function accepts the array to filter, and a function that does the filtering. In this part:
for (var i = 0; i < arr.length; i++) {
var value = arr[i];
if (func(value)) { //here, you invoke the function on the array's values
result.push(value);
}
}
So if, for instance, we look at the inBetween(3, 6) function, which is this:
return function(x) {
return 3 <= x && x <= 6;
}
(If you don't understand this part, read some more about Closures)
So now that function is simply a function that accepts a value and returns true/false on whether or not it's between 3 & 6.
You eventually get an invocation on each of the array's values (1, 2, 3 ... 7) with the above function.
Same goes for all other functions you listed.
In this line:
filter(arr, inBetween(3, 6))
You are not "passing a function", but passing the result from a function call. The result is another (anonymous/unnamed) function.
From this line:
function filter(arr, func) {
We know name the function passed as an argument to filter is named func, then:
if (func(value)) {
executes this function.
In JavaScript, a function is just an object like other objects. To differentiate "function object reference" from "function calls", you can look for ().
inBetween is a function object reference, inBetween(x, y) means calling this function.
Anonymous functions can be defined, assigned to a variable, and passed as an argument as well. It may be executed instantly after definition as well:
function() {
alert("called!");
}();
This may look exotic to people new to JavaScript though.
I have the following problem:
I want to call my functions func1(), func2() & func3() in a random order.
But i want to be sure that every function is called!
If it's possible it also would be nice that no functions are used; just a random order of code sequences.
Like this:
function xy(){
//Call this sequence first second or third
doSomething1
//Call this sequence first second or third
doSomething2
//Call this sequence first second or third
doSomething3
//!! But call each sequence !!
}
Thanks in advance ;)
You could put all function names as strings into an Array, then sort this array randomly and call the functions:
var funcArr = new Array("func1", "func2", "func3");
shuffle(funcArr); //You would need a shuffle function for that. Can be easily found on the internet.
for (var i = 0; i < funcArr.length; i++)
window[funcArr[i]]();
EDIT: If you don't want functions but lines of code to be sorted randomly, then that's not going to work. JavaScript does not have a goto command (at least not without an external API), so you can't jump between code lines. You can only mix functions, as shown above.
You can use something like the Fisher-Yates shuffle for shuffling the functions and then call them via Array.prototype.forEach():
var a = function () { alert('a'); },
b = function () { alert('b'); },
c = function () { alert('c'); },
array = [a, b, c];
array = array.map(function (a, i, o) {
var j = (Math.random() * (o.length - i) | 0) + i,
t = o[j];
o[j] = a;
return t;
});
array.forEach(function (a) { a(); });
There is many ways to do that, one of the most easy way is like this:
Array.prototype.shuffle = function () {
this.sort(function() { return 0.5 - Math.random() });
}
[func1, func2, func3].shuffle().forEach(function(func, index, array){
func();
});
function fibonacci(n) {
return (function(a, b, i) {
return (i < n) ? arguments.callee(b, a + b, i + 1) : a;
})(1, 1, 1);
}
Hey, I am a rookie, I could understand the math logical part of this function, what I did not understand is the parameter passing progress, it passes (1,1,1) to the function(a b i), which seems not very normal.
function fibonacci(n) {
return (function(a, b, i) {
return (i < n) ? arguments.callee(b, a + b, i + 1) : a;
})
regular function pass a parameter like the way function(1 1 1)
}
I can not understand this, I tried to abstract it into finally the
function fibonacci(n){
return()()
}
format, but how could this pass the parameter, I guess it is something about the return call could not handle a function call after it which also works in it.
So, is there some basic stuff I havent learnt? Like some default format like the entries in MDN?
Thnx a lot.
return (function(a, b, i) {
return (i < n) ? arguments.callee(b, a + b, i + 1) : a;
})(1, 1, 1);
is an anonymous function expression that is immediately invoked. The parenthesis around it are not required.
The usage of arguments.callee is deprecated, this would better have been written with a named function expression:
return (function recurse(a, b, i) {
return (i < n) ? recurse(b, a + b, i + 1) : a;
})(1, 1, 1);
which is equivalent to the function declaration and invocation
function recurse(a, b, i) {
return (i < n) ? recurse(b, a + b, i + 1) : a;
}
return recurse(1, 1, 1);
Your final abstraction is wrong. It's not return()() but it is:
return ( function(){} )()
Note that the () does not belong to return since return is not a function. In this case, () act as grouping parenthesis. In the same way when you use it like:
return (1+1)*2
Here, adding *2 behind the () works because the parenthesis is not part of a function invocation but is instead used as a grouping operator. Or more precisely, an expression evaluator.
You see, how (1+1)*2 works is that the () is recognized as not being part of a function call, thus it's contents are treated as an expression. So it is parsed as:
temporary_variable = 1+1;
temporary_variable * 2;
In the same way, (function(){})() is parsed as:
temporary_variable = function(){};
temporary_variable();
Thus, the whole thing is basically doing this:
function f (n) {
temporary_variable = function (a,b,i) {
/* ... */
}
return temporary_variable(1,1,1);
}