Is there a built-in way to check if a javascript function has been called recursively (directly or indirectly)?
By recursively, I mean that the function could be anywhere in the recursion chain (the function doesn't have to be the direct invoker).
EDIT
Obviously, there's no built-in way to achieve what I want to do. I though the plan B would be easy to implement so I came up with this solution (similar to Paolo answer):
function checkRecursion() {
var f = arguments.callee.caller;
var caller = f;
while (caller) {
caller = caller.caller;
if (caller === f) {
return true;
}
}
return false;
};
This function is working perfectly if you try to search the first recursive level.
function fA() {
if (checkRecursion()) {
alert("End of recursion");
}
else {
fB();
}
}
function fB() {
fA();
}
fA();
However, if you need to perform the same check on a function executed after an other recursion, you'll end up into an infinite loop:
var count = 0;
function fA() {
if (checkRecursion()) {
//I should get here but I get stuck in the checkRecursion()
alert("End of recursion");
}
else {
fB();
}
}
function fB() {
if (count > 2) {
fA();
} else
{
count++;
fC();
}
}
function fC() {
fB();
}
fA();
For some reason, the fB caller is fC, and the fC caller is fB so I can't travel back to the fA function as a caller of fB. This issue is way more complicated than I though it would be.
If you reflect on it, what you are getting makes perfect sense because every function in your code is a single object.
caller is a reference to that object and the latter is always the same and so they are its instance variables' values.
In other words, if a function is present more than once in the stack trace then it's "caller" appears to be always the most recent caller. That's why your function fails to go up the stack trace and ends in a infinite loop in the above case.
Let's make an example:
a => b => c => d => b => e => checkRecursion
The above is the stack trace that ends in checkRecursion at the deepest level.
b is called the first time from a the second time from d.
But what you get from caller is that b is always called from d !
It cannot have two callers because the object/function is always the same.
Climbing the stack trace you get
e <= b <= d <= c <= b <= d <= c <= b <= d...
You never reach a
To achieve what you need you may obtain the stack trace with another technique that, unfortunately, is not cross browser.
Below there is a modified version of checkRecursion that uses that technique. I tested it on Firefox, it doesn't work on Safari.
// returns true if the caller appears more than once
// in the stack trace
function checkRecursion()
{
// the name of the calling function
var fname = checkRecursion.arguments.callee.caller.name;
// obtain the stack trace ***not cross browser***
// tested on Firefox
var err = new Error();
var stack = err.stack.split('\n');
// returns true if the calling function appears more than once
var i,n,cnt;
n = stack.length;
cnt = 0;
for( i = 0; i < n; i++ )
{
if( fname == stack[i].substr(0,stack[i].indexOf('#')) )
{
cnt++;
if( cnt > 1 )
{
return true;
}
}
}
return false;
}
You can use the Chrome Developer Tool (if you use chrome) and start a new "Timeline" audit.
If you filter the result to show only the functions, you should be able to find some functions called by time.
Another thing to try is a "profile" audit to collect JavaScript CPU Profile. If you see a function name with an high percentage, that means it's using more resources and it may also be called multiple times.
Using Function.caller, you can check which function invoked your function. Check it against the last caller to see if they're the same function.
var y = function() {
console.log(this.lastCaller === y.caller);
this.lastCaller = y.caller;
}
var x = function(i) {
y();
if(i) {
x(--i);
}
}
x(3);
Outputs:
false, true, true, true
Related
We're going to make a decorator, caching computed results of deterministic functions (for simplisity let's assume one-argument functions).
In common case is could be done this way:
function makeCacheable(origFunc){
let registry = {};
return function (a){
if (a in registry){
return registry[a];
}
let res = origFunc(a);
registry[a] = res;
return res;
}
}
A problem appears when origFunc is recursive: only top-level calls go through the wrapping cache, but the rest of recursive call stack doesn't meet the cache. No need to explain why this happens. I wonder is there a natural way to make a recursive function cacheable in the same manner?
function fibonacciF(n) {
if (n <= 2) return 1;
let a = 1, b = 1;
for (let i = 2; i < n; ++i){
[a, b] = [b, a+b];
}
return b;
}
function fibonacciR(n) {
return n <= 2 ? 1 : (fibonacciR(n-1) + fibonacciR(n-2));
}
let fiboF = makeCacheable(fibonacciF); // OK
let fiboR = makeCacheable(fibonacciR); // actually is not what expected
The function calls a function named fibonacciR. If you want to make this call go through the cache, you have to overwrite fibonacciR:
fibonacciR = makeCacheable(fibonacciR);
Is there a natural way to make a recursive function cacheable in the same manner?
No. In general, a function implementation cannot be inspected, and it doesn't make a difference whether it's implemented recursively or with a loop or something else. Using pure functional programming, we can only use the whole function as a building block for the cached version (fiboR), but we cannot alter its behaviour or take only parts of the function unless the implementation is cooperative (e.g. by using some kind of recursion operator that can be user-supplied).
In the above solution, we break these rules by overwriting a variable that is used inside the function, but this is not always possible even in JavaScript.
You could make it work, if you would use the same (function) variable for storing the decorated version of it. To allow for returning back to the original, you could add a property original to the function object:
function makeCacheable(origFunc){
let registry = {};
let f = function (a){
if (a in registry){
console.log(`retrieving value from registry[${a}]`);
return registry[a];
}
let res = origFunc(a);
registry[a] = res;
return res;
}
// Add property for exposing the original function:
f.original = origFunc;
return f;
}
function fibonacciR(n) {
console.log(`Called fibonnacci(${n})`);
return n <= 2 ? 1 : (fibonacciR(n-1) + fibonacciR(n-2));
}
// Demo illustrating the registry is being used:
console.log('Call fibonnacciR(5) with cache turned on:');
var fibonacciR = makeCacheable(fibonacciR);
var f5 = fibonacciR(5);
console.log(`Result: fibonnaciR(5) = ${f5}`);
// Demo illustrating the function can be restored:
console.log('Call fibonnacciR(5) with cache removed:');
fibonacciR = fibonacciR.original;
f5 = fibonacciR(5);
console.log(`Result: fibonnaciR(5) = ${f5}`);
.as-console-wrapper { max-height: 100% !important; top: 0; }
For example: I have a lot of functions and use them many times.
I need to count calls for each function.
What is the best practice to make it?
At first i thought i need closures, but I can't implement it in a right way.
In the simplest case, you can decorate each function with a profiling wrapper:
_calls = {}
profile = function(fn) {
return function() {
_calls[fn.name] = (_calls[fn.name] || 0) + 1;
return fn.apply(this, arguments);
}
}
function foo() {
bar()
bar()
}
function bar() {
}
foo = profile(foo)
bar = profile(bar)
foo()
foo()
document.write("<pre>" + JSON.stringify(_calls,0,3));
For serious debugging, you might be better off with a dedicated profiler (usually located in your browser's console).
You could try something like this:
<script>
var aCalls = 0;
var bCalls = 0;
function a()
{
aCalls = aCalls + 1;
alert(aCalls);
}
function b()
{
bCalls = bCalls + 1;
alert(bCalls);
}
</script>
var count = 0;
function myfunction()
{
count++;
alert( "Function called " + count);
}
myfunction();
myfunction();
http://jsfiddle.net/xsdzpmwm/3/
The best way is to use a profiler.
On IE: press F12 to open developer tools, then go to the Profiler tab, and hit the play button. After stopping the profiler, you'll be presented with a lot of info (number of calls for each function, inclusive time, exclusive time, etc.)
On Chrome: press F12, go to Profiles, Collect JavaScript CPU Profile (that won't tell you the number of calls though)
My approach would add a property “count” to the function itself.
Just add one line at the beginning of your function you want to have tracked calls.
function func() {
func.count = (func.count || 0) + 1;
// first time you call the function func.count is undefined so use 0 instead
console.log("hi");
}
func();
console.log(func.count) // 1
func();
func();
func();
console.log(func.count) // 4
Functions are objects in javascript after all. No pollution of global namespace, no wrapping or closures needed, very simple to understand and to write.
I can create a recursive function in a variable like so:
/* Count down to 0 recursively.
*/
var functionHolder = function (counter) {
output(counter);
if (counter > 0) {
functionHolder(counter-1);
}
}
With this, functionHolder(3); would output 3 2 1 0. Let's say I did the following:
var copyFunction = functionHolder;
copyFunction(3); would output 3 2 1 0 as above. If I then changed functionHolder as follows:
functionHolder = function(whatever) {
output("Stop counting!");
Then functionHolder(3); would give Stop counting!, as expected.
copyFunction(3); now gives 3 Stop counting! as it refers to functionHolder, not the function (which it itself points to). This could be desirable in some circumstances, but is there a way to write the function so that it calls itself rather than the variable that holds it?
That is, is it possible to change only the line functionHolder(counter-1); so that going through all these steps still gives 3 2 1 0 when we call copyFunction(3);? I tried this(counter-1); but that gives me the error this is not a function.
Using Named Function Expressions:
You can give a function expression a name that is actually private and is only visible from inside of the function ifself:
var factorial = function myself (n) {
if (n <= 1) {
return 1;
}
return n * myself(n-1);
}
typeof myself === 'undefined'
Here myself is visible only inside of the function itself.
You can use this private name to call the function recursively.
See 13. Function Definition of the ECMAScript 5 spec:
The Identifier in a FunctionExpression can be referenced from inside the FunctionExpression's FunctionBody to allow the function to call itself recursively. However, unlike in a FunctionDeclaration, the Identifier in a FunctionExpression cannot be referenced from and does not affect the scope enclosing the FunctionExpression.
Please note that Internet Explorer up to version 8 doesn't behave correctly as the name is actually visible in the enclosing variable environment, and it references a duplicate of the actual function (see patrick dw's comment below).
Using arguments.callee:
Alternatively you could use arguments.callee to refer to the current function:
var factorial = function (n) {
if (n <= 1) {
return 1;
}
return n * arguments.callee(n-1);
}
The 5th edition of ECMAScript forbids use of arguments.callee() in strict mode, however:
(From MDN): In normal code arguments.callee refers to the enclosing function. This use case is weak: simply name the enclosing function! Moreover, arguments.callee substantially hinders optimizations like inlining functions, because it must be made possible to provide a reference to the un-inlined function if arguments.callee is accessed. arguments.callee for strict mode functions is a non-deletable property which throws when set or retrieved.
You can access the function itself using arguments.callee [MDN]:
if (counter>0) {
arguments.callee(counter-1);
}
This will break in strict mode, however.
You can use the Y-combinator: (Wikipedia)
// ES5 syntax
var Y = function Y(a) {
return (function (a) {
return a(a);
})(function (b) {
return a(function (a) {
return b(b)(a);
});
});
};
// ES6 syntax
const Y = a=>(a=>a(a))(b=>a(a=>b(b)(a)));
// If the function accepts more than one parameter:
const Y = a=>(a=>a(a))(b=>a((...a)=>b(b)(...a)));
And you can use it as this:
// ES5
var fn = Y(function(fn) {
return function(counter) {
console.log(counter);
if (counter > 0) {
fn(counter - 1);
}
}
});
// ES6
const fn = Y(fn => counter => {
console.log(counter);
if (counter > 0) {
fn(counter - 1);
}
});
I know this is an old question, but I thought I'd present one more solution that could be used if you'd like to avoid using named function expressions. (Not saying you should or should not avoid them, just presenting another solution)
var fn = (function() {
var innerFn = function(counter) {
console.log(counter);
if(counter > 0) {
innerFn(counter-1);
}
};
return innerFn;
})();
console.log("running fn");
fn(3);
var copyFn = fn;
console.log("running copyFn");
copyFn(3);
fn = function() { console.log("done"); };
console.log("fn after reassignment");
fn(3);
console.log("copyFn after reassignment of fn");
copyFn(3);
Here's one very simple example:
var counter = 0;
function getSlug(tokens) {
var slug = '';
if (!!tokens.length) {
slug = tokens.shift();
slug = slug.toLowerCase();
slug += getSlug(tokens);
counter += 1;
console.log('THE SLUG ELEMENT IS: %s, counter is: %s', slug, counter);
}
return slug;
}
var mySlug = getSlug(['This', 'Is', 'My', 'Slug']);
console.log('THE SLUG IS: %s', mySlug);
Notice that the counter counts "backwards" in regards to what slug's value is. This is because of the position at which we are logging these values, as the function recurs before logging -- so, we essentially keep nesting deeper and deeper into the call-stack before logging takes place.
Once the recursion meets the final call-stack item, it trampolines "out" of the function calls, whereas, the first increment of counter occurs inside of the last nested call.
I know this is not a "fix" on the Questioner's code, but given the title I thought I'd generically exemplify Recursion for a better understanding of recursion, outright.
Using filter and map, recursion example removing null properties from an object
const obj = {
name: {
first: "Jeson",
middle: null,
last: "Holder"
},
age: 45
}
function removeNullOrEmpty(obj){
return Object.fromEntries(
Object.entries(obj)
.filter(([_, v])=> v!== null && v.length !== 0)
.map(([k, v])=>[k, v === Object(v)?removeNullOrEmpty(v):v])
)
}
console.log(removeNullOrEmpty(obj))
What is the maximum recursion depth in Google Apps Script scripts? I have a function, match_recurse, which looks like the following pseudocode:
function match_recurse(array) {
for (i=0, i<3, i++) {
var arr2 = array.copy().push(i);
if (is_done(arr2)) break;
match_recurse(arr2);
}
}
(It also returns its results, but I don't want to bloat the question.)
Now, because the execution errored, the execution transcript and the logs were not saved, so I have no way of knowing whether my is_done function is doing its job wrong. I can do a few cases of the problem on paper and check recursion depth, but I don't know what the maximum is supposed to be.
Looking on the web, I saw an article mentioning that IE has a max call stack of 13 if you go through the Window object, but nothing else.
It is 1000, as one can see from here:
function recurse(i) {
var i = i || 1;
try {
recurse(i+1);
} catch (e) {
Logger.log(i);
}
}
The stack depth value is not documented. Executing the following code shows that this value is equal to 1000.
function getStackDepth(curvalue) {
try {
curvalue = getStackDepth(curvalue) + 1;
}
catch(err) {
}
return curvalue;
}
function test() {
var depth = getStackDepth(2);
debugger;
}
//I have the following function:
function handle_message(msg)
{
//do work
console.log('some work: '+msg.val);
//call next message
msg.next();
}
//And array of message objects:
var msgs = [ {val : 'first msg'}, { val : 'second msg'}, { val : 'third msg'}];
//I link messages by setting next parameter in a way that it calls handle_message for the next msg in the list. Last one displays alert message.
msgs[2].next = function() {alert('done!')};
msgs[1].next = function() {handle_message(msgs[2]);};
msgs[0].next = function() {handle_message(msgs[1]);};
//Start the message handle "chain". It works!
handle_message(msgs[0]);
//======== Now I do exactly the same thing but I link messages using the for loop:
for (var i=msgs.length-1; i>=0; i--)
{
if (i==msgs.length-1)
{
msgs[i].next = function() {alert('done!');};
}
else
{
msgs[i].next = function() {handle_message(msgs[i+1]);};
}
}
//Start the message handling chain. It fails! It goes into infinite recursion (second message calls itself)
handle_message(msgs[0]);
Can sombody explain why it happens? Or maybe an alternative to this pattern? My case is this: I receive an array with messages and I have to handle them in order, one ofter another SYNCHRONOUSLY. The problem is some of the messages require firing a series of animations (jqwuery animate() which is async) and the following messages cannot be handled until the last animation is finished. Since there is no sleep() in javascript I was trying to use such pattern where the message calls the next one after it is finished (in case of animations I simply pass the 'next' function pointer to animate's "complete" callback). Anyway, I wanted to build this 'chain' dynamically but discovered this strange (?) behaviour.
You need a closure to make it work:
function handle_message( msg ) {
console.log( 'some work: ' + msg.val );
msg.next();
}
var msgs = [{val :'first msg'},{val:'second msg'},{val:'third msg'}];
for ( var i = msgs.length - 1; i >= 0; i-- ) {
(function(i) {
if ( i == msgs.length - 1 ) {
msgs[i].next = function() { alert( 'done!' ); };
} else {
msgs[i].next = function() { handle_message( msgs[i + 1] ); };
}
})(i);
}
handle_message( msgs[0] );
Live demo: http://jsfiddle.net/simevidas/3CDdn/
Explanation:
The problem is with this function expression:
function() { handle_message( msgs[i + 1] ); }
This function has a live reference to the i variable. When this function is called, the for loop has long ended and the value of i is -1. If you want to capture the current value of i (the value during the iteration), you need to an additional wrapper function. This function captures the current value of i permanently (as an argument).
I think the problem is that i doesn't have the value you think it has:
// i is defined here:
for (var i=msgs.length-1; i>=0; i--)
{
if (i==msgs.length-1)
{
msgs[i].next = function() {alert('done!');};
}
else
{
msgs[i].next = function() {
// when this line gets executed, the outer loop is long finished
// thus i equals -1
handle_message(msgs[i+1]);
};
}
}
See point #5 Closures in loops at http://blog.tuenti.com/dev/top-13-javascript-mistakes/
Think about the values you are capturing in the closure.
msgs[i].next = function() {handle_message(msgs[i+1]);};
This captures the value of i, but it changes the next iteration so you get an infinite loop.
By the end of the loop i is -1 so i+1 is going just going to be the same message over and over again.