Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
1

How many times can I call a function from inside a function?

Asked by 8 years ago

Essentially, how many iterations would this script be stable for in practical use?

i = 0
function fire()
    wait()
    i = i+1
    print(i)
    fire()
end
fire()

I'm also running a test from my side, but if anyone has an answer, it would be appreciated as I would like to know if it is a common practice for coding states ect.

3 answers

Log in to vote
3
Answered by
BlueTaslem 18071 Moderation Voter Administrator Community Moderator Super Administrator
8 years ago

Functions that call themselves are called recursive.

When you call a function, you compute it, and get it's result, and then keep working. Because you need to "keep working" with all of your local variables in-tact, you have to set aside a chunk of "stack" for each 'deeper' call.

Eventually, you run out, and this is called a stack overflow.

You can approximate the size of the stack by doing something like this:

_G.c = 0
function f()
    _G.c = _G.c + 1
    f()
end

f()

print(_G.c) --> 16381

(The Lua stack is much bigger than most programming languages' defaults. You don't normally hit it unless it's never going to be done)

However, I can use tail recursion to make this not happen.

c = 0
function g()
    c = c + 1
    return g()
end

g() -- never stops

Because you are explicitly returning just the result of the function call, you don't need to "remember" the current function, and thus it takes no extra resources.

This is called a tail call, and it's basically equivalent to not using recursion at all.

The key is to return exactly one function call (and don't do anything with the result).

return f()
return f(1, 2, 3)
return f(1 + 9 + g()) -- g() here is NOT a tail call, but f() is
return f(f(x)) -- the inside f() is NOT a tail call but the outside f() IS
return 1 + f() -- this is NOT a tail call
return f(), f() -- this is NOT a tail call

If what you mean is something as simple as "keep doing this time after time", you should use iteration, since that's the clearer way of describing what you mean.

However, doing things recursively definitely makes more sense sometimes.


Tail Recursion Example

Here's a normal recursive definition of factorial

function factorial(n)
    if n == 0 then
        return 1
    end
    return n * factorial(n - 1)
end

Notice that since I'm doing something to the result of the factorial(n-1) call, this is not a tail recursive call.


To write this tail-recursively, we're going to instead write a similar function. That function I'll just call f. f(n, c) will return n! * c.

In particular, that means

f(n, c) = n! * c = n*(n-1)! * c = (n-1)! * (n*c) = f(n - 1, n * c)

Note that we've avoided doing anything to the result of f this time!

function f(n, c)
    if n == 0 then
        return c
    end
    return f(n - 1, n * c)
end

function factorial(n)
    return f(n, 1)
end
Ad
Log in to vote
0
Answered by 8 years ago

16380 iterations has caused a stack overflow.

Log in to vote
0
Answered by 8 years ago

You are looking on whether or not calling a function works to call a function.

So you can do such an action Example A

function Callme(number)
if number==0 then
print(number);
end
return Callme(number-1)
end
Callme(100);
counts down to 100
--a lua recursion example
tablee == {2,3,4}
function  endOfTable(nondiction)--prints everything in a table , that does not have dictionaries*
return endOfTablez(nondiction,1);-- we start at 1 because a table begins at 1, but in other languages we begin at 0
end
function endOfTablez(nondiction,start)-- according to lua rules we cannot have two of the same functions named the same name with different parameters
    --print(start)
    if(nondiction[start+1] == nil)then
        return nondiction[start];
    else
        print(nondiction[start])
    start = start +1;


 return endOfTablez(nondiction,start)   
    end

end

print(endOfTable(tablee))

As a result, recursion is possible, you just need a case when it defaults and then affect something to get the case to happen.

Answer this question