I have been programming in Java for several years; however, I am now taking a course that Fortran uses as an example code (standard 77). Although I always viewed Fortran as an ancient language, I decided to try the latest version of the 2003 standard, using the gfortran compiler to see its virtues for myself. So far, I have been surprised by modern features, but I ran into one problem, as the example below shows.
module mod1 type type1 real :: x real :: y contains procedure :: compute end type type1 contains subroutine compute(this) class(type1) :: this this%y = this%x*2 - 1 write (*,*) this%x,this%y end subroutine end module mod1 module mod2 type type2 real :: x real :: y contains procedure :: compute end type type2 contains subroutine compute(this) class(type2) :: this this%y = this%x - 5 write (*,*) this%x,this%y end subroutine end module mod2 program test use mod1 use mod2 implicit none type(type1) myType1 type(type2) myType2 myType1%x = 4 myType2%x = 5 call myType1%compute call myType2%compute end program test
This results in a compilation error: "Type mismatch in the 'this' argument to (1), passed TYPE (type2) to CLASS (type1)" with respect to the call myType2%compute statement.
My problem is with the area. It seems that with the help of the class(<class_name>) :: this operator, the compiler should be able to bind the routine to a specific derived type or its descendants. Hence, it does not seem fundamentally difficult for the compiler to search for a definition of a variable starting locally in a subroutine, and then continuing the ancestor tree of a particular this instance. This will eliminate all explicit expressions of this% , which tend to make it difficult to read my type-related procedures after a few statements. For instance,
this%tempNew(xI) = this%lamda*this%temp(xI-1)+(1-2*this%lamda)*this%temp(xI)+this%lamda*this%temp(xI+1)
seems a lot less readable / writable than
tempNew(xI) = lamda*temp(xI-1)+(1-2*lamda)*temp(xI)+lamda*temp(xI+1)
In the latter case, this is pretty obvious through the class(<class_name>) :: this , where each variable must be bound.
Another consequence is that it seems that two separate derived types cannot have associated routines with the same name (as shown by the error message). I saw two common ways. First, you must explicitly call each subroutine, somehow like compute_type1 and compute_type2 . When accessing these routines, it looks very ugly and redundant in code. For example, call myType1%compute_type1 . The second option (see, for example, An overloaded fortran interface with different ranks , Overloading a function with string binding in Fortran 2003 ), which seems better, is to distinguish between the binding name and the procedure name. For example, a type definition would include procedure :: compute type => compute_type1 . This solves the problem of accessing the subroutine, but I see problems when developing large projects with many derived types that implement the same binding name. I would prefer not to keep track of the names of the routines that I have, and not use them in any particular project. This will ultimately keep the names pretty long and less readable.
So my question has three components:
- Are there any cleaner alternatives to explicitly typing
this%<var_name> for class members in type-bound procedures? - Is there a way for the compiler to recognize that the procedure should be bound based on the
class(<class_name>) :: this ? Current subroutine / function name overloading methods are apparently an artifact of the 90/95 standard that does not allow them to be associated with types. - If not, is there a performance increase associated with this implementation? Both of these questions seem to be considered during compilation, and I will gladly sacrifice them to improve the power of expression.