I’m starting a new category of posts called “Code Snippets” where I share code I find interesting.
In this first installment is a simple code snippet I originally wrote in Powershell to scan a local port continuously and do something when the port is found:
1function deploy():
2 if ( port_exists(port) ):
3 do_something()
4 else:
5 deploy()
6
7deploy()
Recursion has been a hard concept for me to put into practice and this served as a good introduction to it. However, this doesn’t feel like a ‘proper’ recursion to me.
I was so satisfied with this code so I showed it to my programmer co-worker friend. He asked me what will happen if the program doesn’t ever find the port? I didn’t think much of it because I know the user can just close the program and the port scanning is slow enough (around 1 sec for each function call).
I later realized what he meant. Being a better programmer than me, he knew something was missing. And so, let’s try to improve the code.
1function deploy(retries):
2
3 if ( retries < 1 ):
4 raise Exception("Port not found, Maximum retries reached.")
5
6 if ( port_exists(port) ):
7 do_something()
8 else:
9 deploy(retries-1)
10
11# Limit retries to n
12n = 10
13deploy(n)
This feels more like recursion. The program will now only do a maximum of n
retries. After that, if the port still doesn’t exist, it will throw an error.
The reason why I said the previous code didn’t feel like a proper recursion was because it didn’t limit the number of times it can call itself.
This limit is called the base case. In the code:
1function deploy(retries):
2
3 if (retries < 1 ): # <--- This is the Base case
4 raise Exception("Port not found, Maximum retries reached.")
5
6 if ( port_exists(port) ):
7 do_something()
8 else:
9 deploy(retries-1)
10
11# Limit retries to n
12n = 10
13deploy(n)
The base case is a condition where if it is true, it stops the recursion.
Without the base case, some recursive functions could result to infinite recursions — something that should not happen, hence why the computer will throw an error (usually a stack overflow) when it finds an infinite recursive function.
For example, you can try to run this python code:
1def a(b):
2 return a(b+1)
3
4a(1)
In this code, nothing will stop a
from calling itself again which could be
problematic. This is why adding the base case and a way to achieve the base
case is important.
Back to the code snippet, what else can we do to improve the code?
Here’s an idea: add a time.sleep() before each recurse to prevent the code from executing too fast and eating unnecessary memory:
1import time
2function deploy(retries):
3
4 if (retries < 1 ):
5 raise Exception("Port not found, Maximum retries reached.")
6
7 if ( port_exists(port) ):
8 do_something()
9 else:
10 time.sleep(1) # <--- Do a 1-second sleep before every recurse
11 deploy(retries-1)
12
13# Limit retries to n
14n = 10
15deploy(n)
Without the time.sleep(1)
, the program will loop as fast as it can, faster
than what the code needs to be which will just waste our computer’s resources
especially if the port_exists
function consumes a lot of memory or cpu when
called.
Note: I mentioned earlier that the port scanning takes 1 second so adding a time.sleep(1) will make the program scan every 2 seconds. I didn’t add that to my original code but in this case, I added it since it’s a different program.
That’s it for this code snippet. Try to improve the code, and maybe publish it. I will be happy to read them :).
To end this episode, I’ll give you something to think about. Here’s the same program but instead of recursion, it uses a while loop:
1function deploy(retries):
2
3 while not port_exists(port):
4 if ( retries < 1 ):
5 raise Exception("Port not found, Maximum retries reached.")
6 retries -= 1
7
8 do_something()
9
10# Limit retries to n
11n = 10
12deploy(n)
Practice your programming skills and think of these questions:
- What are the advantages and disadvantages of using recursion or iteration (i.e. a while loop)?
- What types of situations does it make sense to use recursion versus iteration?
I will leave you, the reader to answer these questions. See you in the next Code Snippet!