At the end of this section of code, you call main() after prompting the user if they want to encode/decode another item. This construction works, but it is generally not necessary and can cause your program to crash in extreme cases. Calling a function again from within the same function is known as "recursion" and can be a powerful technique for solving otherwise difficult problems. Recursive functions allocate storage from the process address space (specifically the stack) which is not infinite. Unchecked recursive functions can quickly consume all memory available to the process which causes them to crash.
Admittedly, your users would have to request millions (or more) of encode/decode iterations before you run into the problem with your code but it's not a good habit to get into :)
I would suggest code structured like:
def main() -> None:
while True:
try:
selection = input("Option [E]ncode [D]ecode [Q]uit").lower()
except KeyboardInterrupt:
break
if selection == "e":
encode()
continue
if selection == "d":
decode()
continue
if selection == "q":
break
print(f"Unknown option {selection}.")
print("Thanks for all the fish!")
The while True loop is an infinite loop that will never stop unless the break keyword is encountered or an exception is raised. I've wrapped the input call in a try/execpt that catches the KeyboardInterrupt exception that the user can cause if they break out of the input call (eg, using a control-C in Linux/MacOS). In later versions of python (3.10 and later) we can use structural pattern matching which is similar to case statements found in C descended languages. Here, since there only a few options I've just used a series of if statements to find out what the user selected and call the appropriate functions. Once a valid selection has been found, the continue keyword is used to cause execution to return to the top of the while loop. In the event of a KeyboardInterrupt exception or the user typing a Q or q the break keyword is used to stop the execution of the loop.
Again, there is nothing wrong with recursive functions if you understand the consequences of using them and plan accordingly.
This particular case doesn't really need a recursive approach IMHO :)
Thank you @JnyJny for the thorough explanation and succinct solution! While I've briefly learned about recursion, I was unaware of the nuances and specific use cases. Much appreciated!
https://github.com/adamdoty/ta-dah-morse-code-translator/blob/4981c2733167861115ef953a5455a7d883b30056/src/ta_dah_morse_code_translator/console.py#L12-L21
At the end of this section of code, you call
main()
after prompting the user if they want to encode/decode another item. This construction works, but it is generally not necessary and can cause your program to crash in extreme cases. Calling a function again from within the same function is known as "recursion" and can be a powerful technique for solving otherwise difficult problems. Recursive functions allocate storage from the process address space (specifically the stack) which is not infinite. Unchecked recursive functions can quickly consume all memory available to the process which causes them to crash.Admittedly, your users would have to request millions (or more) of encode/decode iterations before you run into the problem with your code but it's not a good habit to get into :)
I would suggest code structured like:
The
while True
loop is an infinite loop that will never stop unless thebreak
keyword is encountered or an exception is raised. I've wrapped theinput
call in a try/execpt that catches theKeyboardInterrupt
exception that the user can cause if they break out of the input call (eg, using a control-C in Linux/MacOS). In later versions of python (3.10 and later) we can use structural pattern matching which is similar to case statements found in C descended languages. Here, since there only a few options I've just used a series ofif
statements to find out what the user selected and call the appropriate functions. Once a valid selection has been found, thecontinue
keyword is used to cause execution to return to the top of the while loop. In the event of a KeyboardInterrupt exception or the user typing aQ
orq
thebreak
keyword is used to stop the execution of the loop.Again, there is nothing wrong with recursive functions if you understand the consequences of using them and plan accordingly.
This particular case doesn't really need a recursive approach IMHO :)