Reputation: 43
Evening, novice here, i've been trying to use tail recursion using the Function object but when i call the function again in it's body and evaluate it, it returns an error signaling that it hasn't been defined. I want to know if it's posssible to use the Function object recursively because i want to makek a function with it that takes any amount of argument, and the only way i can think of to solve it, is using recursion
var sum = new Function('...args',
'if(args.length==2) return args[0] + args[1]; else return args[0] + sum(...args.slice[1]);');
/*
-console.log(sum(1, 2));
->returns: 3
-console.log(sum(1, 2, 3));
->returns: Error: sum is not defined
*/
I made the same function the regular way and it worked like i expected:
function sum2(...args){
if(args.length==2) return args[0] + args[1];
else return args[0] + sum2(...args.slice(1));
}
/*
-console.log(sum2(1, 2));
->returns: 3
-console.log(sum2(1, 2, 3));
->returns: 6
*/
Upvotes: 0
Views: 60
Reputation: 29116
To quote MDN:
Functions created with the Function constructor do not create closures to their creation contexts; they always are created in the global scope. When running them, they will only be able to access their own local variables and global ones, not the ones from the scope in which the Function constructor was created. This is different from using eval with code for a function expression.
So, this does not work because var sum
is not in the global scope. Here is an example:
/* global scope */
var dummyRecursion = new Function('stop',
`console.log("invoke with", stop);
if(!stop) dummyRecursion(true)`);
dummyRecursion(false);
/* functional scope */
function main() {
var dummyRecursion = new Function('stop',
`console.log("invoke with", stop);
if(!stop) dummyRecursion(true)`);
dummyRecursion(false);
}
main();
If you really need to use the new Function
construct to dynamically generate functions and want to use tail recursion, then you can create an inner function and invoke it - that way you will always have visibility to it:
/* global scope */
var dummyRecursion = new Function('stop',
`var innerFn = function(stop) {
console.log("invoke with", stop);
if(!stop) innerFn(true)
}
innerFn(stop);`);
dummyRecursion(false);
/* functional scope */
function main() {
var dummyRecursion = new Function('stop',
`var innerFn = function(stop) {
console.log("invoke with", stop);
if(!stop) innerFn(true)
}
innerFn(stop);`);
dummyRecursion(false);
}
main();
Upvotes: 1