There's a few magic words that are used by programmers to describe different kinds of functions. Here's a few:
- Re-entrant
- ThreadSafe
- Referentially Transparent
- Idempotent
- Pure
- Side-Effects
You can look some of them up if you want a headache. The point is that Computer science and engineering progress has always been about reducing complexity. We have spent quite a lot of time thinking about the best way to write a function to achieve that goal. Hopefully, you can stuff tiny bits of your program into your head at a time, and understand those bits, without having to also understand the overall functioning of the entire program simultaneously, or the detailed implementation of the insides of all the other functions. A function that uses global variables can't do that very well because:
- You can't guarantee that the global variables exist
- You can't guarantee that the global variables are what you think they are
- You can't guarantee that other parts of the program haven't modified those variables in a way you didn't expect.
- You can't easily generalise to use the function multiple times on multiple sets of variables.
- You can't easily verify that the function works as advertised without first setting up the function's external environment and its dependencies.
- If the global variables have changed in a way you didn't expect, it's really hard to track down which part of the program is the culprit. It could be any of 500 different functions that write to that variable!
On the other hand, if you explicitly pass in all the data a function needs to operate, and explicitly return all the results:
- If something goes wrong with any of those variables, it's easy to find the source of the problem
- It's easier to add code to verify the "domain" of your inputs. Is it really a string? Is it over a certain length, is it under a certain length? Is it a positive number? is it whole, or fractional? All these assumptions that your code needs to operate correctly can be explicit at the start of the function, instead of just crossing your fingers and hoping nothing goes wrong.
- It's easier to guess what a particular function will actually do, if its output depends only on its input.
- a function's parameters are not dependant on the naming of any external variables.
And other advantages.