So this has been bugging me. For example, takes a string input and draws its function. So I am wondering how it takes a basic string and returns a function that can be run. Not desmos.com specifically they're just a good example.
How would one return a working function from a string?
Every way I look at it if you return function()... it will try and run the function and return it right then.
Eg:
var string = "x^2";
//return
function f = (x) => {
return x * x;
}
Edit: expanding to try and explain better, it is a bit difficult to explain.
function generate_f = (string) => {
return f(x);
}
f = generate_f("x^2");
returns: a function that can be called, eg to draw the function to a canvas.
function f = (x) => { return Math.pow(x, 2); }
f = generate_f("x^3 + 4");
function f = (x) => { return Math.pow(x, 3) + 4; }
Imagine I ran the string through a parser, I tokenize "x^3 + 4" into an array ["x", "^", 3, "+", 4] I loop through I see x, check next value see ^ and then 3 I then add Math.pow(x, 3) to a thing, as it checks for a power value, then I add to that thing +4, now if I did this it would break at Math.pow(x, 3) as there is no x value so how would you return a working function.
I believe you'd have to do some parsing of the string to get the full functionality you're looking for.
A decent library you can play with is http://mathjs.org/docs/expressions/parsing.html
Use JavaScript's Function Constructor.
For example:
var square = Function("x", "return Math.pow(x,2)");
square(2); // 4
Generating a dynamic function
You have the right idea for your generate_f function. You will just have to use the Function constructor to turn the string input into a function that may be called.
function generate_f(expression){
// use Function constructor
// to build a new function
// from the 'expression' string argument
var customFunction = Function("x", "return " + expression);
return customFunction;
}
var myFunction = generate_f("Math.pow(x,3) + 4;");
myFunction(2); // 12
Arguments
You will notice that in the above examples the Function constructor is used to create functions with a single argument, x. If you want to build a function that accepts more arguments, you may use a comma-delimited list or one string per argument.
Example:
// function arguments defined using a comma-delimited list
var sum = Function("x, y, z", " return x + y + z; ");
// function arguments defined using one string per argument
var add = Function("a", "b", " return a + b; ");
var i = sum(1, 2, 3); // 6
add(i, 1); // 7
If you are generating a function that does not accept any arguments, just provide the function body expression.
var functionBody = " return 'This function has no arguments.'; ";
var noArgs = Function(functionBody);
noArgs(); // This function has no arguments.
Notes
Any leading arguments to the Function constructor are parameters to your generated function. The last argument to the Function constructor is always the function body.
When using the Function constructor remember to always type capital letter F:
// function constructor (returns a new function)
var myFunction = Function(functionArgument, functionBody);
// function declaration (declares a function)
myFunction = function(){ /* expression */ };
The generate_f function could be rewritten as such:
function generate_f(){
var args = Array.prototype.slice.call(arguments);
var nArguments = args.length;
var functionBody;
if(nArguments == 1){ // build function with no arguments (function body only)
functionBody = args[0];
return Function(functionBody);
}else if(nArguments > 1){ // build function that accepts arguments
functionBody = args.pop(); // remove last argument (the function body)
// form a comma-delimited list
// from the remaining arguments (the leading arguments)
var functionParameters = args.join(',');
return Function(functionParameters, functionBody);
}
return false;
}
Then you could use generate_f to build the functions from each example:
var square = generate_f("x", " return Math.pow(x,2); ");
var myFunction = generate_f("x", " return Math.pow(x,3) + 4; ");
var sum = generate_f("x, y, z", " return x + y + z; ");
var add = generate_f("a", "b", " return a + b; ");
var noArgs = generate_f(" return 'This function has no arguments.'; ");
This is called string parsing. In fact, it is exactly how a web browser takes your JavaScript code and makes the computer do something. You only need to convert the mathematical expression into some form that can be evaluated. You do not need to convert it into JavaScript. You can do the parsing by hand or user a library to help you. I suggest you do further research on string parsing.
Related
I'm learning javascript and I found this exercise:
function abc(a){
return(function(y){
return y--**--y+1;
})(++a)+a;
}
document.write(abc(2));
The output of that is 7 and I dont understand why, I searched information about nested functions and I didnt found anything....
How is "y" defined?
this function translates to:
//I've replaced the arguments and the vars with the actual values
function abc(){
function innerFunction(){
return (3 ** 1) + 1
}
return innerFunction(3) + 3
}
//or written differently
function abc(a){
function innerFunction(v){
//v--
var tmp1 = v;
v = v-1;
//--v
v = v-1;
var tmp2 = v;
return Math.pow(tmp1, tmp2) + 1;
}
a = a+1; //++a
return innerFunction(a) + a;
}
That is easy.
Function abc return (function(y){ return y--**--y+1; })(++a)+a
this means if a is 2 (function(3){ return y--**--y+1; }) + 2
This contains an immediately invoked function expression (IIFE).
Here's an example that might clarify how they work:
(function(x) { return x; })(10); // Returns 10
The value inside the parenthesis is used as the function's argument as soon as the function is defined. So, in this case, the function is set to return the argument, and immediately afterwards, it is given the value 10.
On your example, with some added whitespace:
return (function(y) {
return y-- ** --y + 1;
})(++a)
+ a
What's happening is the same. A function is being defined then, immediately afterwards, it receives the argument ++a. It will replace all instances of y by the value contained in ++a. Then, as that is returned, it goes through + a, so it adds a to the result.
I'm trying to solve a puzzle, and am at my wit's end trying to figure it out.
I'm supposed to make a function that works like this:
add(1); //returns 1
add(1)(1); //returns 2
add(1)(1)(1); //returns 3
I know it can be done because other people have successfully completed the puzzle. I have tried several different ways to do it. This is my most recent attempt:
function add(n) {
//Return new add(n) on first call
if (!(this instanceof add)) {
return new add(n);
}
//Define calc function
var obj = this;
obj.calc = function(n) {
if (typeof n != "undefined") {
obj.sum += n;
return obj.calc;
}
return obj.sum;
}
//Constructor initializes sum and returns calc(n)
obj.sum = 0;
return obj.calc(n);
}
The idea is that on the first call, a new add(n) is initialized and calc(n) is run. If calc receives a parameter, it adds n to sum and returns itself. When it eventually doesn't receive a parameter, it returns the value of sum.
It makes sense in theory, but I can't get it to work. Any ideas?
--edit--
My code is just the route I chose to go. I'm not opposed to a different approach if anyone can think of one.
To answer "how dow this work". Given:
function add(n) {
function calc(x) {
return add(n + x);
}
calc.valueOf = function() {
return n;
}
return calc;
}
var sum = add(1)(2)(3); // 6
When add is called the first time, it stores the value passed in in a variable called n. It then returns the function calc, which has a closure to n and a special valueOf method (explained later).
This function is then called with a value of 2, so it calls add with the sum of n + x, wich is 1 + 2 which 3.
So a new version of calc is returned, this time with a closure to n with a value of 3.
This new calc is called with a value of 3, so it calls add with n + x, which this time is 3 + 3 which is 6
Again add returns a new calc with n set to 6. This last time, calc isn't called again. The returned value is assigned to the variable sum. All of the calc functions have a special valueOf method that replaces the standard one provided by Object.prototype. Normally valueOf would just return the function object, but in this case it will return the value of n.
Now sum can be used in expressions, and if its valueOf method is called it will return 6 (i.e. the value of n held in a closure).
This seems pretty cool, and sum will act a lot like a primitve number, but it's actually a function:
typeof sum == 'function';
So be careful with being strict about testing the type of things:
sum * 2 // 12
sum == 6 // true
sum === 6 // false -- oops!!
Here's a somewhat streamlined version of #RobG's great answer:
function add(n) {
function calc(x) { return n+=x, calc; }
calc.valueOf = function() { return n; };
return calc;
}
The minor difference is that here calc just updates n and then returns itself, rather than returning itself via another call to add, which puts another frame on the stack.
Making self-replication explicit
calc is thus a pure self-replicating function, returning itself. We can encapsulate the notion of "self replication" with the function
function self_replicate(fn) {
return function x() {
fn.apply(this, arguments);
return x;
};
}
Then add could be written in a possibly more self-documenting way as
function add(n) {
function update(x) { n += x; }
var calc = self_replicate(update);
calc.valueOf = function() { return n; };
return calc;
}
Parallel to Array#reduce
Note that there is a certain parallelity between this approach to repeatedly calling a function and Array#reduce. Both are reducing a list of things to a single value. In the case of Array#reduce the list is an array; in our case the list is parameters on repeated calls. Array#reduce defines a standard signature for reducer functions, namely
function(prev, cur)
where prev is the "accumulator" (value so far), cur is the new value being fed in, and the return value becomes the new value the accumulator. It seems useful to rewrite our implementation to make use of a function with that kind of signature:
function add(n) {
function reducer(prev, cur) { return prev + cur; }
function update(x) { n = reducer(n, x); }
var calc = self_replicate(update);
calc.valueOf = function() { return n; };
return calc;
}
Now we can create a more general way to create self-replication-based reducers based on a reducer function:
function make_repeatedly_callable_function(reducer) {
return function(n) {
function update(x) { n = reducer(n, x); }
var calc = self_replicate(update);
calc.valueOf = function() { return n; };
return calc;
};
}
Now we can create add as
var add = make_repeatedly_callable_function(function(prev, cur) { return prev + cur; });
add(1)(2);
Actually, Array#reduce calls the reducer function with third and fourth arguments, namely the index into the array and the array itself. The latter has no meaning here, but it's conceivable we might want something like the third argument to know what "iteration" we're on, which is easy enough to do by just keeping track using a variable i:
function reduce_by_calling_repeatedly(reducer) {
var i = 0;
return function(n) {
function update(x) { n = reducer( n, x, i++); }
var calc = self_replicate(update);
calc.valueOf = function() { return n; };
return calc;
};
}
Alternative approach: keeping track of values
There are certain advantages to keeping track of the intermediate parameters the function is being called with (using an array), and then doing the reduce at the end instead of as we go along. For instance, then we could do Array#reduceRight type things:
function reduce_right_by_calling_repeatedly(reducer, initialValue) {
var array_proto = Array.prototype,
push = array_proto.push,
reduceRight = array_proto.reduceRight;
return function(n) {
var stack=[],
calc = self_replicate(push.bind(stack));
calc.valueOf = reduceRight.bind(stack, reducer, initialValue);
return calc(n);
};
}
Non-primitive objects
Let's try using this approach to build ("extend") objects:
function extend_reducer(prev, cur) {
for (i in cur) {
prev[i] = cur[i];
}
return prev;
}
var extend = reduce_by_calling_repeatedly(extend_reducer);
extend({a: 1})({b: 2})
Unfortunately, this won't work because Object#toValue is invoked only when JS needs a primitive object. So in this case we need to call toValue explicitly:
extend({a: 1})({b: 2}).toValue()
Thanks for the tip on valueOf(). This is what works:
function add(n) {
var calc = function(x) {
return add(n + x);
}
calc.valueOf = function() {
return n;
}
return calc;
}
--edit--
Could you please explain how this works? Thanks!
I don't know if I know the correct vocabulary to describe exactly how it works, but I'll attempt to:
Example statement: add(1)(1)
When add(1) is called, a reference to calc is returned.
calc understands what n is because, in the "mind" of the interpreter, calc is a function child of add. When calc looks for n and doesn't find it locally, it searches up the scope chain and finds n.
So when calc(1) is called, it returns add(n + x). Remember, calc knows what n is, and x is simply the current argument (1). The addition is actually done inside of calc, so it returns add(2) at this point, which in turn returns another reference to calc.
Step 2 can repeats every time we have another argument (i.e. (x)).
When there aren't any arguments left, we are left with just a definition of calc. The last calc is never actually called, because you need a () to call a function. At this point, normally the interpreter would return a the function object of calc. But since I overrode calc.valueOf it runs that function instead.
When calc.valueOf runs, it finds the most recent instance of n in the scope chain, which is the cumulative value of all previous n's.
I hope that made some sense. I just saw #RobG 's explanation, which is admittedly much better than mine. Read that one if you're confused.
Here's a variation using bind:
var add = function _add(a, b) {
var boundAdd = _add.bind(null, a + b);
boundAdd.valueOf = function() {
return a + b;
}
return boundAdd;
}.bind(null, 0);
We're taking advantage of a feature of bind that lets us set default arguments on the function we're binding to. From the docs:
bind() also accepts leading default arguments to provide to the target
function when the bound function is called.
So, _add acts as a sort of master function which takes two parameters a and b. It returns a new function boundAdd which is created by binding the original _add function's a parameter to a + b; it also has an overridden valueOf function which returns a + b (the valueOf function was explained quite well in #RobG's answer).
To get the initial add function, we bind _add's a parameter to 0.
Then, when add(1) is called, a = 0 (from our initial bind call) and b = 1 (passed argument). It returns a new function where a = 1 (bound to a + b).
If we then call that function with (2), that will set b = 2 and it'll return a new function where a = 3.
If we then call that function with (3), that will set b = 3 and it'll return a new function where a = 6.
And so on until valueOf is called, at which point it'll return a + b. Which, after add(1)(2)(3), would be 3 + 3.
This is a very simple approach and it meets the criteria the OP was looking for. Namely, the function is passed an integer, keeps track of that integer, and returns itself as a function. If a parameter is not passed - the function returns the sum of the integers passed to it.
let intArray = [];
function add(int){
if(!int){
return intArray.reduce((prev, curr) => prev + curr)
}
intArray.push(int)
return add
}
If you call this like so:
console.log(add(1)(1)());
it outputs 2.
How to define a function in Javascript with n number of parenthesis. For example if we have a sum function , we should be able to call it as below
sum(2)(1)(5);
and it should return 8, where the number of parenthesis can be 1 to n.
This should be close enough
function sum(x) {
var _b = x;
var f = function(n) {
_b += n;
return f;
}
f.valueOf = function() {
return _b;
}
return f;
}
console.log( sum(1)(2)(3) + 1 );
Note that the best you can do still requires a trick to get a value from the function that just has to return another function (so that you can call it again).
The trick consists in defining valueOf/toString so that a value of the internal buffer is returned when necessary.
What you're asking for is not exactly possible. The problem is in that if you want to chain functions, each has to return a function.
Now you want the final call to return a number, but how could the function know when to return the final value instead of a function?
You could however pass any number of arguments to a function, and access them with arguments.
function sum(/*num1, num2, num3, ..., numN*/) {
return [].reduce.call(arguments, function(sum, num) {
return sum + num;
}, 0);
}
console.log(sum(1, 2, 3));
Or alternately, store the sum in the outer scope and never return the value.
var sum = 0;
function add(num) {
sum += num;
return add;
}
add(1)(2)(3);
console.log(sum);
In JavaScript a value cannot be both a function and a number at the same time, so you somehow need to indicate that you want to have the number after the last argument was passed to it.
One way to do this, is to let the function return the sum value when you pass it no argument (an extra pair of parentheses):
sum(2)(3)(6)()
This you can implement like this:
function sum(a) {
return b => b === undefined ? a : sum(a+b);
}
var a = sum(2)(3)(6)();
console.log(a);
An alternative, as suggested also by Wictor, is to use the returned function in way that it will coerce to a number. By defining an appropriate valueOf method you can then define what that number should be when this happens.
This can be combined with the previous method, so that you can actually choose how to get the number value:
function sum(a) {
var f = b => b === undefined ? a : sum(a+b);
f.valueOf = _ => a;
return f;
}
// method 1:
console.log(sum(2)(3)(6)());
// method 2:
console.log(+sum(2)(3)(6));
Note that to coerce to a value to a number, you can use the unitary +.
With Object.assign this can be rewritten in functional programming style:
function sum(a) {
return Object.assign(b => b === undefined ? a : sum(a+b), { valueOf: _ => a });
}
// method 1:
console.log(sum(2)(3)(6)());
// method 2:
console.log(+sum(2)(3)(6));
I trying to make next with closure:
function func(number) {
var result = number;
var res = function(num) {
return result + num;
};
return res;
}
var result = func(2)(3)(4)(5)(3);
console.log(result); // 17
I need to receive 2 + 3 + 4 + 5 + 3 = 17
But I got an error: Uncaught TypeError: number is not a function
You somehow have to signalize the end of the chain, where you are going to return the result number instead of another function. You have the choice:
make it return a function for a fixed number of times - this is the only way to use the syntax like you have it, but it's boring. Look at #PaulS' answer for that. You might make the first invocation (func(n)) provide the number for how many arguments sum is curried.
return the result under certain circumstances, like when the function is called with no arguments (#PaulS' second implementation) or with a special value (null in #AmoghTalpallikar's answer).
create a method on the function object that returns the value. valueOf() is suited well because it will be invoked when the function is casted to a primitive value. See it in action:
function func(x) {
function ret(y) {
return func(x+y);
}
ret.valueOf = function() {
return x;
};
return ret;
}
func(2) // Function
func(2).valueOf() // 2
func(2)(3) // Function
func(2)(3).valueOf() // 5
func(2)(3)(4)(5)(3) // Function
func(2)(3)(4)(5)(3)+0 // 17
You're misusing your functions.
func(2) returns the res function.
Calling that function with (3) returns the number 5 (via return result + num).
5 is not a function, so (4) gives an error.
Well, the (2)(3) part is correct. Calling func(2) is going to return you res, which is a function. But then, calling (3) is going to return you the result of res, which is a number. So the problem comes when you try to call (4).
For what you're trying to do, I don't see how Javascript would predict that you're at the end of the chain, and decide to return a number instead of a function. Maybe you could somehow return a function that has a "result" property using object properties, but mostly I'm just curious about why you're trying to do things this way. Obviously, for your specific example, the easiest way would just be adding the numbers together, but I'm guessing you're going a bit further with something.
If you want to keep invoking it, you need to keep returning a function until you want your answer. e.g. for 5 invocations
function func(number) {
var result = number,
iteration = 0,
fn = function (num) {
result += num;
if (++iteration < 4) return fn;
return result;
};
return fn;
}
func(2)(3)(4)(5)(3); // 17
You could also do something for more lengths that works like this
function func(number) {
var result = number,
fn = function () {
var i;
for (i = 0; i < arguments.length; ++i)
result += arguments[i];
if (i !== 0) return fn;
return result;
};
return fn;
}
func(2)(3, 4, 5)(3)(); // 17
I flagged this as a duplicate, but since this alternative is also missing from that question I'll add it here. If I understand correctly why you would think this is interesting (having an arbitrary function that is applied sequentially to a list of values, accumulating the result), you should also look into reduce:
function sum(a, b) {
return a + b;
}
a = [2, 3, 4, 5, 3];
b = a.reduce(sum);
Another solution could be just calling the function without params in order to get the result but if you call it with params it adds to the sum.
function add() {
var sum = 0;
var closure = function() {
sum = Array.prototype.slice.call(arguments).reduce(function(total, num) {
return total + num;
}, sum);
return arguments.length ? closure : sum;
};
return closure.apply(null, arguments);
}
console.log(add(1, 2, 7)(5)(4)(2, 3)(3.14, 2.86)); // function(){}
console.log(add(1, 2, 7)(5)(4)(2, 3)(3.14, 2.86)()); // 30;
We can make light work of it using a couple helper functions identity and sumk.
sumk uses a continuation to keep a stack of the pending add computations and unwinds the stack with 0 whenever the first () is called.
const identity = x => x
const sumk = (x,k) =>
x === undefined ? k(0) : y => sumk(y, next => k(x + next))
const sum = x => sumk(x, identity)
console.log(sum()) // 0
console.log(sum(1)()) // 1
console.log(sum(1)(2)()) // 3
console.log(sum(1)(2)(3)()) // 6
console.log(sum(1)(2)(3)(4)()) // 10
console.log(sum(1)(2)(3)(4)(5)()) // 15
I trying to make next with closure:
function func(number) {
var result = number;
var res = function(num) {
return result + num;
};
return res;
}
var result = func(2)(3)(4)(5)(3);
console.log(result); // 17
I need to receive 2 + 3 + 4 + 5 + 3 = 17
But I got an error: Uncaught TypeError: number is not a function
You somehow have to signalize the end of the chain, where you are going to return the result number instead of another function. You have the choice:
make it return a function for a fixed number of times - this is the only way to use the syntax like you have it, but it's boring. Look at #PaulS' answer for that. You might make the first invocation (func(n)) provide the number for how many arguments sum is curried.
return the result under certain circumstances, like when the function is called with no arguments (#PaulS' second implementation) or with a special value (null in #AmoghTalpallikar's answer).
create a method on the function object that returns the value. valueOf() is suited well because it will be invoked when the function is casted to a primitive value. See it in action:
function func(x) {
function ret(y) {
return func(x+y);
}
ret.valueOf = function() {
return x;
};
return ret;
}
func(2) // Function
func(2).valueOf() // 2
func(2)(3) // Function
func(2)(3).valueOf() // 5
func(2)(3)(4)(5)(3) // Function
func(2)(3)(4)(5)(3)+0 // 17
You're misusing your functions.
func(2) returns the res function.
Calling that function with (3) returns the number 5 (via return result + num).
5 is not a function, so (4) gives an error.
Well, the (2)(3) part is correct. Calling func(2) is going to return you res, which is a function. But then, calling (3) is going to return you the result of res, which is a number. So the problem comes when you try to call (4).
For what you're trying to do, I don't see how Javascript would predict that you're at the end of the chain, and decide to return a number instead of a function. Maybe you could somehow return a function that has a "result" property using object properties, but mostly I'm just curious about why you're trying to do things this way. Obviously, for your specific example, the easiest way would just be adding the numbers together, but I'm guessing you're going a bit further with something.
If you want to keep invoking it, you need to keep returning a function until you want your answer. e.g. for 5 invocations
function func(number) {
var result = number,
iteration = 0,
fn = function (num) {
result += num;
if (++iteration < 4) return fn;
return result;
};
return fn;
}
func(2)(3)(4)(5)(3); // 17
You could also do something for more lengths that works like this
function func(number) {
var result = number,
fn = function () {
var i;
for (i = 0; i < arguments.length; ++i)
result += arguments[i];
if (i !== 0) return fn;
return result;
};
return fn;
}
func(2)(3, 4, 5)(3)(); // 17
I flagged this as a duplicate, but since this alternative is also missing from that question I'll add it here. If I understand correctly why you would think this is interesting (having an arbitrary function that is applied sequentially to a list of values, accumulating the result), you should also look into reduce:
function sum(a, b) {
return a + b;
}
a = [2, 3, 4, 5, 3];
b = a.reduce(sum);
Another solution could be just calling the function without params in order to get the result but if you call it with params it adds to the sum.
function add() {
var sum = 0;
var closure = function() {
sum = Array.prototype.slice.call(arguments).reduce(function(total, num) {
return total + num;
}, sum);
return arguments.length ? closure : sum;
};
return closure.apply(null, arguments);
}
console.log(add(1, 2, 7)(5)(4)(2, 3)(3.14, 2.86)); // function(){}
console.log(add(1, 2, 7)(5)(4)(2, 3)(3.14, 2.86)()); // 30;
We can make light work of it using a couple helper functions identity and sumk.
sumk uses a continuation to keep a stack of the pending add computations and unwinds the stack with 0 whenever the first () is called.
const identity = x => x
const sumk = (x,k) =>
x === undefined ? k(0) : y => sumk(y, next => k(x + next))
const sum = x => sumk(x, identity)
console.log(sum()) // 0
console.log(sum(1)()) // 1
console.log(sum(1)(2)()) // 3
console.log(sum(1)(2)(3)()) // 6
console.log(sum(1)(2)(3)(4)()) // 10
console.log(sum(1)(2)(3)(4)(5)()) // 15