I want to use an index variable inside a recursion, without sending it as a parameter when calling the function. However, if I reset it at the beginning (e.g i = 0), it will reset on every run. I want to use it as a counter (to count the function runs).
Share
First of all, you will obviously want to initialize it only once. A common pattern in recursion is:
Where the outer method does nothing but some initialization.
A “solution” you will see suggested often (e.g. in the first comment to your question) will be to use static variables. This approach is a bad style, and will cause your program to fail in various weird way once you add multi-threading (e.g. by making a UI version, or run it in multithreading web server). And the worst is that it may at first appear to work, and only start misbehaving subtly when there are many users. So keep away from “static” for everything except constants!
With “static” it would commonly look like this:
Now imagine that two users invoke
startat the same time. They will overwrite each others counter! Because static means, it’s shared amongst threads and users.Here is a really simple to understand solution:
You then create a task, run it, and retrieve the counter at the end. Clean, dead simple, efficient and reliable. If you have more than one thread/user, each will have a separate MyTask object, and you won’t run into any problem.
Plus, you can add additional statistics, and they are all cleanly wrapped in the task object. “Average time per iteration”? “Average recursion depth”? No problem. The task object can also be used to store your result.
The use of
ThreadLocalhas been suggested here. I do not agree with this. It offers no benefits of the task object at all. Just try to implement it withThreadLocaland the task object and you’ll see the difference. Plus,ThreadLocalis empirically 10x slower than accessing heap values (see https://stackoverflow.com/a/4756605/1060350 ). Forintit likely is even worse. So never ever callThreadLocal#getin a performance critical codepath. If you intend to useThreadLocal, use it outside of this codepath, and use a local variable (or a Task object) to feed the “local static” variable into your critical codepath.