If a task can be carried out in a function (returns one value), are there advantages (other than convention and brevity) of using a function rather than a subroutine to perform this task?
I ask, because a) I often found that explicit calls (accompanied by intent specifications in the subroutine) made me understand what’s going on more quickly even if it increased the total line number a little, b) I will be modernising some old code and considered replacing pure functions with pure subroutines in some instances (primarily for clarity where a function is somewhat analogous to a subroutine).
So I wonder if :
there is something I am currently not thinking of that should stop me from considering b),
what your opinions are on this with regards to clarity/readability.
Personally, the big downside I see with functions in Fortran as opposed to subroutines is that in a large code base, it is not immediately obvious sometimes when you are looking at a function call vs an element of an array that is defined elsewhere. This is more of a problem in codes using lots of global variables, include statements, etc.
Subroutines are explicitly on their own line like call sub(args) which is easier to identify in my mind. However, it is nice that you can use functions in expressions, so you can avoid having to define a bunch of intermediate results if the expression is simple enough to just do in a single line.
Performance wise, functions and subroutines should be similar. When I’ve tried to measure it in the past, it’s never a huge difference. Sometimes, the subroutine has lesser calling overhead if it’s measurable at all.
EDIT: I will note that you can have functions return arrays or whatever else you want by declaring them like so: function func(args) result(res). At that point, you can define res in the body of the function to be anything you want, derived type, array, etc. Using functions to return more than single values will more often measure slower than a subroutine returning the same thing through intent(out), I believe due to having to allocate and some compilers treatment of expressions creating temporary arrays.
I like to use functions whenever possible to encourage a “functional style” of programming. Especially when when the function is pure/elemental (and soon simple). That is, it receives only inputs from its dummy argument list, and returns a functional result, with no side-effects.
If the procedure needs to have multiple outputs and/or has significant side effects, then it should be coded as a subroutine.
As to being able to distinguish between an array reference and a function call in an expression, a simple coding technique is to place the opening parenthesis exactly next to the array name. In the case of a function or subroutine call, place a space between the procedure name and the opening paren. E.g.:
x = array(i) + func (j) ! Note space between func and (j)
call subr (j) ! again a space between subr and (j) for consistency
A mentor of mine way back in college used to code this way, and it has stuck with me ever since.
Another approach I use is to make all intrinsic functions (on RHS of assignment obviously) all CAPS. For user defined functions I’ll either use all caps or just a leading cap (first letter) for the function name. everything else on RHS of assignments is normally lower case
Thanks for the input. Yes, I have always done this through naming conventions too (“f_[function name]” for functions). Still, I may end up replacing functions with subroutines for simplicity. I’ll consider this for a little longer.
While I do agree that naming conventions is something to be certainly considered and defined in a Project, also for a better personal mental model, I do also think that all these required extra letters or whatever that everyone puts in place to distinguish Fortran Functions from Fortran Arrays would not be required if Fortran had a better and proper tooling, such as the Fortran LSP providing syntax highlighting.
And, since GSoC25 is soon to be coming, this might also be included among the tasks, as I think the whole Fortran Community would benefit from something like this, instead of needing to wrap the head around of whether to prefix functions with f_, or cap here and there, very likely ending to replace them with subroutines, which at least are unique in their syntax.
the output can be assigned indifferently to a classical variable, or to an allocatable variable and taking advantage of the (re)allocate-on-assignment feature
the functional approach, if chosen, makes clear that the arguments are not modified in a call
A limitation of the functional approach in Fortran is that only a single output is possible.
Subroutine pros:
more flexible when multiple outputs are needed
possibly faster as the output variables don’t have to be allocated internally before being copied to another variable on return
error status generally make more sense with subroutines
This is shorter to answer, so I will start there. In the absence of IDE support, you are forced to choose a naming convention (e.g. “f_*” are always functions and nothing else is) and enforce it (with tools). It is preferable not to rely on tools that can be taken away from you.
Read 10.1.7 Evaluation of operands. Functions participate in expressions, subroutines do not. Evaluation of expressions might or might NOT require evaluation of function references, if the processor can determine the value of the expression “otherwise”. This “otherwise” might include mind-reading or time-travel, or, more commonly, incredible feats of optimization. I don’t know of any compiler that avoids evaluating the partial SUMs in
And there is nothing stopping the compiler from reasoning about functions you write in the same way.
On the other hand, and far more likely, the compiler might struggle to optimize away the creation of temporary objects needed for partial results, during expression evaluation (as PierU alluded to).
I expect you are less interested in the theoretical constraints of the language and more interested in the behaviour of current compilers, and that, I am afraid is a mixed bag of pros and cons.
Thanks for the input. I do have functions in a lot of expressions in my old code. The consideration of replacing some with subroutines would involve breaking up existing expression (again, more for readability as part of teaching). But perhaps that’s not so great an idea after all; I may just stick with my previous use of “f_” for function names.
Early fortran, before f66, had the requirement that all function names ended in the letter F.
As others have mentioned, allocation of memory for array-valued and derived-type valued functions, or arguments in the subroutine case, is sometimes very expensive relative to the rest of the effort within the subprogram. That kind of programming convention should be avoided when performance is critical. This is one of the problems with, for example, the matmul() intrinsic function interface – the programmer has no direct control over where and when the storage for the result is allocated, how often it is allocated, and if the same intermediate storage can be reused for multiple matmul() references.
Another problem that arises with functions is when the function result is used in a write statement. Adding an innocent looking debug write statement somewhere down the call chain of function references suddenly causes your program to behave oddly, or to hang, because of the restriction in fortran against recursive i/o.
I remember this thread from last year, Execute_command_line problem. It also involved a function reference in a write statement, seemingly related to recursive i/o but not in an obvious way.