adamdoty / ta-dah-morse-code-translator

Translator that encrypts and decrypts morse code
MIT License
1 stars 0 forks source link

Bug: Use a While Loop in console.py #6

Open JnyJny opened 2 years ago

JnyJny commented 2 years ago

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:

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 :)

adamdoty commented 2 years ago

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!