Here's a simple Fortran95 code that GNU Fortran (gfortran) compiles very well:
Module Module1
Implicit None
Type MyType
Real(Kind=8) :: x, y
Integer :: n
End Type
Contains
Real(Kind=8) Function Calc(self)
Type(MyType) :: self
Calc = self%x**self%n self%y**self%n
End Function
End Module
Program Main
Use Module1
Implicit None
Type(MyType) :: A
A = MyType(3.0, 4.0, 2)
Write(*,*) Calc(A)
End Program Main
In this case, an object A
of the derived type MyType
is created and initialized inside Main
. Calc()
is called and its result printed. Now comes a slightly different code:
Module Module1
Implicit None
Type MyType
Real(Kind=8) :: x, y
Integer :: n
End Type
Type(MyType) :: A
Contains
Real(Kind=8) Function Calc(self)
Type(MyType) :: self
Calc = self%x**self%n self%y**self%n
End Function
End Module
Program Main
Use Module1
Implicit None
A = MyType(3.0, 4.0, 2)
Write(*,*) Calc(A)
End Program Main
Same number of lines, same result. But here A
was assigned to the derived type MyType
within Module1
, and "travels" with it anytime this module is imported/used (Use
) by any other module and therefore A
can be used within this latter module (provided A
had been previously initialized, of course). Works similarly to a global variable, but not quite; modules that don't USE Module1 cannot access A
.
The question is: is there any conceptual problem with this programming "style"? One must, of course, be careful with whatever is done with A
in other modules, but this applies to other variables as well.
I can see a few advantages in the use of these "travelling" objects, but I may be missing something.
CodePudding user response:
In your first example, A
is a local variable, but in your second example, A
is a global variable. There are many reasons why global variables are often a bad idea, explained in depth in various places around Stack Overflow 1 2 3 and Stack Exchange 4.
To give a concrete example, consider the code:
module module2
use module1
implicit none
contains
subroutine foo()
A = MyType(1.0, 2.0, 3)
write(*,*) calc(A)
end subroutine
end module
module module3
use module2
implicit none
contains
subroutine bar()
A = MyType(2.0, 3.0, 3)
call foo()
write(*,*) calc(A)
end subroutine
end module
program main
use module3
implicit none
call bar()
end program main
Rather than printing
9.0
35.0
as might be expected, this instead prints
9.0
9.0
Since any change to A
is necessarily a side effect, these kinds of problems are likely to be very hard to avoid. Note also that module3
does not explicitly use module1
, but rather implicitly uses module1
via use module2
.