Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

DarkBASIC Professional Discussion / Tutorial: Recursion

Author
Message
Libervurto
20
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 25th Jan 2013 16:03 Edited at: 27th Jan 2013 08:02
This short tutorial explains how recursion works and why it is a useful technique in certain situations.
The benefit of recursion is that different procedures can be nested in any combination.
Or to put it another way: "Recursive functions are to functions as functions are to subroutines."

* Subroutines handle one instance of a procedure with one set of parameters.
* Functions handle one instance of a procedure with multiple sets of parameters.
* Recursive functions handle multiple instances of a procedure with multiple sets of parameters.

Let's say we wanted to produce an output that looks like this:


So how would we code something like that? Well let's see it without recursion.


Getting a sense of deja vu when scanning over a block of code is a sure sign that things can be tidied away into conditional loops and/or functions, and these lines certainly look alike! If you're confident with arrays you'll have spotted that we could dump those strings into one and reference them by the index number. That's a good start, but how on earth are we going to deal with that pesky "+tab"? It doesn't appear at regular intervals, and ideally the placement of each tab should be variable so that we can use this code to display more than one message. (It would be a pretty useless program if it couldn't.) What we need is some way of telling the program when to add a tab-space and when to remove one. Maybe we could do this:


Better? Well the problem is that if we want the program to be flexible we'd need a different case statement for each line and use variables for each too. Alternatively we could store the indentation level of each line in another array and reference it like the strings:


Yay! ... What, still not good enough? Well this is much better than what we started with but looking at all those x's is already confusing, and we only have six lines! There's just no good way to get the amount of flexibility we want without using recursion.

Now we're onto the good part! What makes recursion useful is the fact that functions use local variables that have a specific value to that function call. Check out this example:


The output counts up to 4 but the function only returns 1. This demonstrates that the first call hasn't forgotten its value for 'a', but what happened to the subsequent values? Let's make a diagram to help visualize what happens when we run the code:


The difference between the first call and all subsequent calls is that we're storing the return value in 'r', but when we return from the recursive calls to the function 'a' has nowhere to go and is forgotten.
Let's fix that and see what happens:


A tiny change, but an important lesson in recursion.
You might expect the result to be 2, since the first call (the one that actually returns a value to the main program) get's its new 'a' value from the second call, but remember that the 2nd had its 'a' changed by the 3rd call, and the 3rd by the 4th! It's only when we reach the 4th call that 'times' reaches zero, the journey ends and all the function calls collapse in on each other. 'a' is not changed again before 'endfunction a'
so the value from call 4 gets passed right back up to the main program.

Examples

Procedural Island Generator

Spirals:


Recursive Text Parser:
Example Text Parser File:


Have fun playing around with the examples and see what interesting things you can make using recursion.

Meanwhile...
TheComet
18
Years of Service
User Offline
Joined: 18th Oct 2007
Location: I`m under ur bridge eating ur goatz.
Posted: 25th Jan 2013 17:31 Edited at: 25th Jan 2013 19:41
One important thing that should be mentioned in addition to all of this is the potential stack overflow. There is a limit to how deep you can go with recursion, because the stack stores a pointer to every function that hasn't been returned to yet.

I used a recursive function for a flood fill. Here's the C++ code:



Entire code:


And here it is converted to DBP (should work):


The function just requires an array with pixel data in it called "pixel":



It is not the most efficient flood fill function out there, but it's the simplest.

TheComet

http://blankflankstudios.tumblr.com/
"Man being a noob sucks! " - OBese87
GIDustin
18
Years of Service
User Offline
Joined: 30th May 2008
Location:
Posted: 25th Jan 2013 18:36
Quote: " rem set current colour to replacement colour
pixel( posX, posY ) = targetColour"

I think that targetColour should be replaceColour
TheComet
18
Years of Service
User Offline
Joined: 18th Oct 2007
Location: I`m under ur bridge eating ur goatz.
Posted: 25th Jan 2013 19:40
Thanks for pointing that out, fixed.

TheComet

http://blankflankstudios.tumblr.com/
"Man being a noob sucks! " - OBese87
Libervurto
20
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 25th Jan 2013 22:11
I don't like it when lots of people read and only two comment. Was this helpful? Have I made errors or not explained things well?

@Comet
Yes, stack overflow is a danger, thanks for pointing that out. I had not thought of saying that since I was using very simple examples.

Meanwhile...
Zero G Scott
18
Years of Service
User Offline
Joined: 14th Dec 2007
Location: California, USA, Earth, Sol Sys
Posted: 26th Jan 2013 09:06 Edited at: 26th Jan 2013 09:45
Yes this helps a lot OBese87, no worries! Its actually exactly what I need with my latest project since I couldn't figure out how to manage repeating code that had too many variables to simplify further for a function. Now I have a blueprint to try. Thank you!

How can you tell what the stack overflow limit is, if there is one? Trial and error?

Where I got stuck was I didn't realize you were calling the function within itself to create a nesting loop and progress the number values. More emphasize on that might help. When I did follow the logic then the light bulb went on and my mind was BLOWN!
Phaelax
DBPro Master
23
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 26th Jan 2013 13:07
Quote: "How can you tell what the stack overflow limit is, if there is one? Trial and error?"

If you need to know where the limit is (how much ram basically), then your recursive algorithm needs work.

"You're not going crazy. You're going sane in a crazy world!" ~Tick
Zero G Scott
18
Years of Service
User Offline
Joined: 14th Dec 2007
Location: California, USA, Earth, Sol Sys
Posted: 26th Jan 2013 14:06
Yeah it would be rather self evident wouldn't it.
Libervurto
20
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 26th Jan 2013 18:20
@ Zero G Scott
Thanks, I've added a diagram for the code flow within the function.

Meanwhile...
Mage
Valued Member
19
Years of Service
User Offline
Joined: 3rd Feb 2007
Location:
Posted: 27th Jan 2013 02:07
Quote: "One important thing that should be mentioned in addition to all of this is the potential stack overflow."


This is why I switched to Visual Basic up from QBasic way back in the day.

TheComet
18
Years of Service
User Offline
Joined: 18th Oct 2007
Location: I`m under ur bridge eating ur goatz.
Posted: 27th Jan 2013 16:56
Quote: "This is why I switched to Visual Basic up from QBasic way back in the day."


What do you mean? Every language has the potential of a stack overflow when using recursion.

TheComet

http://blankflankstudios.tumblr.com/
"Man being a noob sucks! " - OBese87

Login to post a reply

Server time is: 2026-07-07 04:10:10
Your offset time is: 2026-07-07 04:10:10