Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Emulating namespaces in Fortran 90

One of the most troublesome issues with Fortran 90 is the lack of namespacing. In this previous question "How do you use Fortran 90 module data" from Pete, it has been discussed the main issue of USE behaving like a "from module import *" in Python: everything that is declared public in the module is imported as-is within the scope of the importing module. No prefixing. This makes very, very hard to understand, while reading some code, where a given identifier comes from, and if a given module is still used or not.

A possible solution, discussed in the question I linked above, is to use the ONLY keyword to both limit the imported identifiers and document where they come from, although this is very, very tedious when the module is very large. Keeping the module small, and always using USE : ONLY is a potentially good strategy to work around the lack of namespacing and qualifying prefixes in Fortran 9X.

Are there other (not necessarily better) workaround strategies? Does the Fortran 2k3 standard say anything regarding namespacing support?

like image 210
Stefano Borini Avatar asked Oct 06 '10 16:10

Stefano Borini


1 Answers

No one else summited this suggestion as an answer (though someone did in the comments of one answer). So I'm going to submit this in hopes it may help someone else.

You can emulate namespaces in the following way, and I would hope there would be no noticeable performance hit for doing so from the compiler (if so all object oriented Fortran programming is sufferings). I use this pattern in my production code. The only real downfall to me is the lack of derived type contained parameter variables, but I offer an option for that as well below.

Module Math_M

    IMPLICIT NONE
    
    PRIVATE

    public :: Math

    Type Math_T
        real :: pi=3.14159
    contains
        procedure, nopass :: e => math_e
        procedure :: calcAreaOfCircle => math_calcAreaOfCircle
    End Type

    Type(Math_T) :: Math
    real, parameter :: m_e = 2.71828

    contains

    function math_e() result(e)
        real :: e
        e = m_e
    end function math_e

    function math_calcAreaOfCircle(this, r) result(a)

        class(Math_T), intent(in) :: this
        real, intent(in) :: r

        real :: a

        a = this%pi * r**2.0
    end function math_calcAreaOfCircle
End Module Math_M

And the usage

Program Main

    use Math_M

    IMPLICIT NONE

    print *, Math%pi
    print *, Math%e()
    print *, Math%calcAreaOfCircle(2.0)


End Program Main

Personally I prefer using $ over the _ for module variables, but not all compilers like that without compiler flags. Hopefully this helps someone in the future.

like image 173
QuantumDebris Avatar answered Oct 27 '22 05:10

QuantumDebris