Whenever I write a new procedure, I use the rules of thumb shown in figure 3.8 to decide whether to make it a function or a subroutine.

Figure 3.8 Deciding when to use a subroutine over a function
This is a simple decision-making process that you can follow. If you know your procedure will cause side effects, such as I/O or modifying a variable declared outside of the procedure, use a subroutine. Also, if you need your procedure to return more than one variable as a result, you have no choice but to use a subroutine. However, these are all special cases. The general rule from figure 3.8 boils down to always using a function unless a subroutine is necessary.
Tip Always use a function, unless you have to use a subroutine.
Technically, Fortran allows you to have intent(out) and intent(in out) arguments in functions. This kind of function would both return its normal result and modify one or more of its arguments in place. This inevitably creates side effects that are difficult to debug, and it hinders the compiler from optimizing the program. There’s even a feature of the language designed to prevent side effects: pure procedures. In practice, pure procedures allow you to write code that the compiler can safely optimize, and that potentially can even be executed out of order.