How to embed functions into functions in javascript like this? - javascript

I've just met with a very interesting task to solve, but I can't do it myself.
Make a function which do the following input!
console.log(foo(4)(5)(6)); // output: 120
The solution is not this:
function foo(number1,number2,number3){
return number1 * number2 * number3;
}
In theory it has to use nested functions.

It is called currying. You need to return function which it's case returns a function which returns the total. Here we also use a term called closure.
function foo(a){
return function(b) {
return function(c){
return a * b * c;
}
}
}
console.log(foo(4)(5)(6));
With ES6 syntax
var foo = a => b => c => a*b*c;
console.log(foo(4)(5)(6));
For infinite levels you can do
function foo(value){
infinite.total = value;
function infinite(val) {
infinite.total *= val;
return infinite;
}
infinite.toString = function() { return infinite.total; }
return infinite;
}
console.log(foo(4)(5)(6)(7));
var total = foo(4)(5)(6)(7);
console.log(total);
But this will output the total in that cases, when toString() is called explicitly or implicitly

You could use an approach for any length of repeated calls of the function with returning a function and an implementation of toString method.
var foo = function(value) {
function fn(a) {
fn.value *= a;
return fn;
}
fn.value = value;
fn.toString = function () { return fn.value; };
return fn;
}
console.log(foo(4)(5)(6));
console.log(foo(42));
console.log(foo(42)(44));

try with currying:
function foo(number) {
return function(number2) {
return function(number3) {
return number * number2 number3;
}
}
}
console.log(foo(5)(6)(7));
https://jsfiddle.net/mv9bm3tL/1/
More information : https://www.sitepoint.com/currying-in-functional-javascript/

You need nested functions - currying;
console.log(foo(4)(5)(6)); // output: 120
let first = foo(4);
let second = first(5);
let last = second(6);
console.log(last);
function foo(number1,number2,number3){
return function(number2){
return function(number3){
return number1 * number2 * number3;
}
}
}

Closures in javascript will help you to achieve this.
function foo(a){
return function(b){
return function(c){
return a*b*c;
}
}
}
console.log(foo(4)(5)(6)); //will return 120

Using arrow functions;
var foo = a => b => c => a*b*c;
console.log(foo(4)(5)(6));

Related

How can I get this javascript function to call itself?

As of right now my sum function looks like the code below. It works and returns the sum of the consecutive calls. But how can I make this work without the empty parenthesis at the end? Like so theSum(5)(4)(3) which returns 12.
function theSum(x) {
var total = x;
function rec(y) {
if (y === undefined) return total;
total += y;
return rec;
};
return rec;
}
console.log(theSum(5)(4)(3)()); // 12
Here is a suggestion utilizing a toString method:
function theSum(x) {
var total = x;
function rec(y) {
total += y;
return rec;
};
rec.toString = function() { return total; }
return rec;
}
alert(theSum(5)(4)(3));
console.log(parseInt(theSum(5)(4)(3)));
Note however that you need to convert the returned reference to a string in some way so that you see the result.
This is not possible. A function cannot return a function and an integer. You can make theSum(5, 4, 3) = 12 or theSum([5, 4, 3]) = 12.
Closures and JavaScript duck typing to the rescue:
function NumSumFun(initial){
function NumSumNext(num) {
initial+= num;
return NumSumNext;
}
NumSumNext.valueOf = function () { return initial; }
return NumSumNext;
}
var x = NumSumFun(10)(29); // ==> function 39
x + 1; // ==> 40
So whats happening. It returns a function but the function has a valueOf property that has access to the accumulated value so the function acts as a number when used as a number.

Javascript - how to detect how many functions are being called? (multiple parentheses)

Let me propose an example that works, then follow up with what fails, highlighting the point to my question.
Here, we have 3 functions being called (1 named, 2 anonymous):
var add = function(a, b) {return a+b};
var multiply = function(a, b) {return a*b};
function myFunction(fxn) {
return function(x) {
return function(y) {
return fxn(x,y);
}
}
}
myFunction(add)(2)(3)
Understandably, this call fails:
myFunction(add)(2)(3)(4)
How would I detect how many functions are being called? In the 2nd call, I'm calling 4 functions (1 named, 3 anonymous).
How would I rewrite the myFunction function in a way that compensated for any given amount of calls? I know we can detect how many arguments a function was given, but is there a way to detect how many functions are being called? I hope I worded this correctly. Thanks.
To find out if a variable contains a reference to a function you can use below code:
if (typeof(v) === "function") alert("This is a function")
Based on above you can find out on how many nested functions there are
function myFunction() {
return function() {
return function() {
return 1 + 2;
}
}
}
var count = 0;
var v = myFunction();
while (typeof(v) === "function") {
count++;
v = v();
}
alert("Nr of nested functions: " + count)
Even if this has no practical use case I can think of, this is a possible solution:
var add = function(a, b) {
return a + b
};
var multiply = function(a, b) {
return a * b
};
var counter = 0;
var result = 0;
function myFunction(fxn) {
counter = 1;
result = 0;
return function first(x) {
++counter;
return function second(y) {
++counter;
x = result ? result : x;
result = fxn(x, y);
return second;
}
}
}
myFunction(add)(1)(2)(3)(4);
alert('Result is: ' + result + '; Parentheses count: ' + counter);

"add" function that works with different combinations of chaining/arguments

I'm trying to write an add function that will work in many scenarios.
add(2,2,2) //6
add(2,2,2,2) //8
add(2)(2)(2) // 6
add(2)(2)(2,2).value() //8
add(2,2)(2) + 2 //8
add(2).add(2) //4
add(2,2,2).add(2).add(2,2).value() //12
add(2,2,2).add(2).value() //8
This is what I have so far:
function add(){
var sum = 0;
for( var i in arguments ){
sum += arguments[i];
}
var ret = add.bind(null, sum);
ret.value = function () {
return sum;
}
ret.add = function () {
for( var i in arguments ){
sum += arguments[i];
}
return sum;
}
ret.valueOf = function(){ return sum; };
return ret;
}
console.log(add(2,2,2));
console.log(add(2,2,2,2));
console.log(add(2)(2)(2));
console.log(add(2)(2)(2,2).value());
console.log(add(2,2)(2) + 2);
console.log(add(2).add(2));
console.log(add(2,2,2).add(2).value());
console.log(add(2,2,2).add(2).add(2,2).value());
I am having a problem with the last two cases:
add(2,2,2).add(2).add(2,2).value() //12
add(2,2,2).add(2).value() //8
It seems like I would have to keep nesting the add functions if I wanted to chain more than two together and also add the value function to each of them, but obviously I'm missing something simple that will allow me to chain them as much as I like, and call value on any of them.
Also they need to always return ints (not strings), and it seems like sometimes they do and other times they don't?
Looking at the way you're using arguments in similar ways in two different places, it's clear that you are duplicating functionality and that is why you are running into this problem with having to "infinitely nest" the .value() method.
The key thing to recognize is that add() can return a function that references itself as its own add property. This will allow add(1,2)(3) to behave exactly the same as add(1,2).add(3). This can be done like so:
function add() {
var sum = Array.prototype.reduce.call(arguments, function(l, r) {
return l + r;
}, 0);
var ret = add.bind(null, sum);
ret.add = ret;
ret.value = ret.valueOf = Number.prototype.valueOf.bind(sum);
ret.toString = Number.prototype.toString.bind(sum);
return ret;
}
snippet.log(add(2,2,2));
snippet.log(add(2,2,2,2));
snippet.log(add(2)(2)(2));
snippet.log(add(2)(2)(2,2).value());
snippet.log(add(2,2)(2) + 2);
snippet.log(add(2).add(2));
snippet.log(add(2,2,2).add(2).value());
snippet.log(add(2,2,2).add(2).add(2,2).value());
snippet.log(add(1, 2, 3)(4, 5).add(6, 7)(8).add(9, 10));
snippet.log(add(5,4)(3).add(2)(1) * 10);
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
There are still two potential issues with the above approach, one minor and one a little less minor:
There are property references and function definitions that are re-executed every time the add function is used (including during chaining)
If someone overwrites the add identifier, it would cause the whole implementation to break:
function add() {
var sum = Array.prototype.reduce.call(arguments, function(l, r) {
return l + r;
}, 0);
var ret = add.bind(null, sum);
ret.add = ret;
ret.value = ret.valueOf = Number.prototype.valueOf.bind(sum);
ret.toString = Number.prototype.toString.bind(sum);
return ret;
}
var myAdd = add;
add = "boom!";
myAdd(1, 2, 3); // TypeError: add.bind is not a function
Both of these can be remedied with an IIFE:
var add = (function () {
var reduce = Array.prototype.reduce,
np = Number.prototype,
valueOf = np.valueOf,
toString = np.toString,
plus = function (l, r) { return l + r; };
return function add() {
var sum = reduce.call(arguments, plus, 0);
var ret = add.bind(null, sum);
ret.add = ret;
ret.value = ret.valueOf = valueOf.bind(sum);
ret.toString = toString.bind(sum);
return ret;
}
})();
var myAdd = add;
add = "U Can't Touch This"; // hammertime
snippet.log(myAdd(1, 2, 3)(4, 5).add(6, 7)(8).add(9, 10));
snippet.log(myAdd(5,4)(3).add(2)(1) * 10);
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
I have tried to improvise with the use of this. Works for all cases.
function add(){
var sum = this instanceof Number?this: 0;
for( var i in arguments ){
sum += arguments[i];
}
var ret = add.bind(sum);
ret.add = ret;
ret.value = ret.valueOf = function() { return sum; };
ret.toString = sum.toString.bind(sum);
return ret;
}
JS-Fiddle
Since you are returning the sum in the ret.add function thats why the error is coming try something like this, hope it will solve your problem
function add(){
var sum = 0;
for( var i in arguments ){
sum += arguments[i];
}
var ret = add.bind(null, sum);
ret.value = function () {
return sum;
}
ret.add = function () {
for( var i in arguments ){
sum += arguments[i];
}
return ret;
}
ret.valueOf = function(){ return sum; };
return ret;
}
Also they need to always return ints (not strings), and it seems like sometimes they do and other times they don't?
Yeah, this is definitely a conceptual problem. These two things you want aren't compatible. Is add(2,2,2) a number or something with an add method?
add(2,2,2) //6
add(2,2,2).add(2).value() //8
Even if there is a fancy way to add methods to nubmers, I would highly recommend keeping things simple and always requiring a ".value()" call to end the chain. This way all calls to ".add" return an "adder object" and all calls to ".value" return a regular number.
it seems like I would have to keep nesting the add functions if I wanted to chain more than two together and also add the value function to each of them, but obviously I'm missing something simple that will allow me to chain them as much as I like, and call value on any of them.
The answer to this is to use recursive functions. Here is a function that creates the "adder" object I mentioned previously:
function sumArray(arr){
var s = 0;
for(var i=0; i<arr.length; i++){
s += arr[i];
}
return s;
}
function mkAdder(currSum){
return {
value: function(){
return currSum;
},
valueOf: function(){
return currSum;
},
add: function(/**/){
return mkAdder(currSum + sumArray(arguments));
}
}
}
Then your initial add function would look like this:
function add(/**/){
return mkAdder(sumArray(arguments));
}

Sum custom objects like numbers (Javascript)

I'm new on Javascript. I'm trying to do this exercise, but i cannot found anything to help me with that.
I created this object
var Foo = function(value) {
this.val = value;
}
And now I need sum two Foo objects with + operator.
var first = new Foo(2);
var second = new Foo(3);
var result = first + second; //should be 5
Do I have a way to overload operator + (like c++) , declare my Foo object as an Integer or something like that?
var result = first.val + second.val;
alert(result); // 5
jsfiddle: http://jsfiddle.net/czhE3/
UPD
OK, without val:
var Foo = function(value) {
this.val = value;
this.toString = function() {
return this.val;
}
}
var first = new Foo(2);
var second = new Foo(3);
var result = first + second;
alert(result); // 5
http://jsfiddle.net/czhE3/1/
As the previous people have mentioned you cannot override operators in javascript, but you could implement a valueOf which is the arithmetic version of a toString().
Add the follow code line:
Foo.prototype.valueOf = function () { return this.val; };
or
this.valueOf = function () { return this.val; };
Working fiddle http://jsfiddle.net/fJJL9/
There is no way in Javascript to overload operators as in C++. The closest thing you can make is a sum function for your objects, like
function sum ( a, b ) { return a.value + b.value; }

how can i implement this logic add(1)(2)(1).. upto (n)?

I know this question is already answered with limited capability but I want it with n number of time with n arguments?
function add(x) {
return function(y) {
if (typeof y !== 'undefined') {
x = x + y;
return arguments.callee;
} else {
return x;
}
};
}
add(1)(2)(3)(); //6
add(1)(1)(1)(1)(1)(1)(); //6
problem is this works only when I add extra empty brackets ()
it doesn't work if do this add(1)(2)(3)
reference question
Try this:
function add(x) {
var fn = function(y) {
x = x + y;
return arguments.callee;
};
fn.toString = function(){ return x; };
return fn;
}
The following code works exactly like you asked:
function add(a)
{
var c=a,b=function(d){c+=d;return arguments.callee;};
b.toString=function(){return c;}return b;
}
Do note that some operations will detect the result given as a function, but any functions that require a string or integer will see the proper value.
Try sending your numbers as an array and changing your function code to reflect these changes.
Note: Code untested.
function add(x) {
var result = 0;
for (i = 0; i < x.length;i++){
result+=x[i];
}
return result;
}
add(new Array(1,2,3));

Categories