# What is good practice for protecting parent scope variables in Fortran?

So I just picked up a project that is written in fortran90. I am used to coding in python and C.

What is really troubling for me is the use of subroutines in fortran90. In fortran people use subroutines to set variables of the parentscope in a sub function. This is really intransparent for me since tracking changes of those variables gets really difficult if the code becomes more complex. What I mean is this, compare these snippets:

subroutine big()
implicit none
integer :: a

a=1
call f()
print *,a

contains

subroutine f()
implicit none
a = 2
end subroutine f

end subroutine big

program hello
call big()
end program hello


2

Similarly in python I am protected from overwriting a:

def big():
a=1
def f():
a=2

f()
print(a)

big()


1

In python I cannot simply set a in a subfunction (except I use a global statement which is bad practice), in fortran I can and people are doing it.

• What is the proper way/ good coding practice to write modern fortran code where parent scope variables are protected?
• As a start, I would consider it good practice to pass the values which are used as parameters to the subroutine. That self-documents that something might happen to the argument, and that it is needed/used within. I would also consider it best practice to refrain from having subroutines within your routines. If I remember correctly you may sort bigger chunks of functionality into modules in fortran and explicitly state what you want to use from those (similar to NameSpace::function() in C/C++) Oct 11 '19 at 14:07

There are several tools to make a codebase more structured. In your example, the subroutine within big() is called without arguments, but changes something in the outer scope, as you said. To prevent something like this, you may of course explicitly state the argument to the function:

subroutine big()
implicit none
integer :: a
a=1
call f(a)
print *,a

contains
subroutine f( argument )
implicit none
type(Complex), intent(inout) :: argument
argument = 2
end subroutine f
end subroutine big


This shows the reader that something will happen to a! There are also explicit intent statements ready to specify what kind of arg argument actually is. (Is it only an input which should not be changed?!)

Generally speaking the more you expose the -intent- of what the code is supposed to be doing, the easier you make it for the reader to work with it.

There is also the module system, where you may sort different subroutines/functions into a module, and thereby structure your code into different segments. What these segments are depends strongly on your case, but using modules may greatly clearify what the subroutine is supposed to be doing, without even looking at it.

lets say you sorted all your linear algebra stuff into a module called linAlg. You may then use:

in some other place, and the reader will have enough hints to get whats going on.

So my two cents of keeping a monstrosity of a fortran codebase at bay is:

1. encapsulate into comparatively small modules to keep namespaces small and self-document your intent with each module (linear_algebra_mod, finiteElement_mod,solvers_mod, vectorTypes_mod,matrixTypes_mod, inputOutput_mod etc.). Once you did that, you can then explicitly state what you want to use out of them, eg.: "use a_mod, only : foo, bar"
2. explicitly state the inputs/outputs of subroutines and functions and make use of the intent statements
3. Use concise but meaningful subroutine/function names which are self-explanatory (If there is to much happening in one sub, then split it up into smaller parts)
4. use expressive variable names. Do not go down the road of naming your variables: i, ii, ij, ji, ijk, ikk, ikkijasdf :-)
5. Use a reasonable ammount of input checks within important subroutines. If your method gets lots of NaN's as an input, or you try to calculate the square root of -1.0, you better be informed right there and not after a 3 hour debugging session!
6. Very important: avoid premature optimization. Just because the nerd in your department knows all the tricks to tickle out another 10% of perf doesn't mean that readability of your codebase is irrelevant. Focus on performance only when you actually run into problems.

Depending on how big your project is, you may also port it to even newer versions of Fortran (2008), where you can encapsulate into classes! (OOP in Fortran)

• This is, in fact, good advice for any programming language! Oct 14 '19 at 2:11
• what changes if I have access to Fortran 2008? Is the problem I have mentioned obsolete then? Oct 14 '19 at 8:01
• What I was also hoping for is a mechanism that prevents me from setting parent scope variables in a local function, like a security option. Is there anything existing like this? Oct 14 '19 at 8:25
• @MrPuh, Not that I am aware of. You might be lucky and there is some compiler warning, that you might be able to switch on, but I don't know that by heart, sorry. As for the newer Fortran, I think to remember that encapsulation got a lot better with the newer revisions. But the decision of moving to newer versions depends strongly on the size of your codebase and your task within it. Oct 14 '19 at 12:49