Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

VBA "OOP" and Fortran 2003

NotThatItMatters
Beginner
2,746 Views

I have been doing a great deal of proof-of-concept work in MS Excel with VBA macros.  The idea is to get these macros/algorithms working on a spreadsheet and then transfer them without too much change to Fortran.

The current problem lies with form.  I have created a module which makes use of three class modules in VBA.  The class module A is a solver, as in it has algorithms for solving equations.  Class module B is a function base class with function prototypes for use by the solver.  Class module C is an override of B which has the actual implementation of function(s)/subroutine(s) for the solver.

I call class A with reference to class C, and the solver thus knows which functions and subroutines to use for the solving.  I would like to use something equivalent on the Fortran side, but am unsure of the constructs.  I need to be able to let the Fortran module A have functions and subroutines outside of the module which it can access with the names not being hard-wired.  I recognize Fortran 2003 has this capability, but I am unaware of the particulars.

Is there a forum topic or a book/web-site which may give me a clue as to how to implement this?

0 Kudos
19 Replies
Steven_L_Intel1
Employee
2,746 Views

I discuss several good books that would help in Doctor Fortran in "It's a Modern Fortran World"

0 Kudos
NotThatItMatters
Beginner
2,746 Views

Thank you.  I have "Modern Fortran Explained" by Metcalf, Reid and Cohen.  I am having a bit of trouble understanding procedure pointers and the like.  I am assuming this is what I need but have as yet to determine this.  I have not yet devised the actual algorithms needed to solve the problem at hand, so there remain many problems that still require my inspiration and perspiration.

0 Kudos
Steven_L_Intel1
Employee
2,746 Views

No, I think you'd do this with type-bound procedures, type extension and procedure overriding. Procedure pointers would not likely enter into it, though I suppose they could.

0 Kudos
NotThatItMatters
Beginner
2,746 Views

The terminology is causing me some grief.  I have programmed in OOP, and am familiar with the terms superclass/subclass and the like.

I would assume when you are saying "type-bound procedures" and "type extension" and "procedure overriding" you are speaking of a superclass (base class) being extended by a subclass (child class) with the overridden procedures being in the type extension.  Again, this all became utterly confused when I discovered the Fortran 2003 keyword "class".

0 Kudos
Steven_L_Intel1
Employee
2,746 Views

Terminology does vary, but your assumptions are basically correct.

0 Kudos
NotThatItMatters
Beginner
2,746 Views

I have begun the coding of this subtlety in Fortran 2003.  Let me quote the code which is not compiling:

module FuncBase_Module
use PRECISION_SPECIFICATION
implicit none
type FuncBase
contains
    procedure :: Func
    procedure :: FuncV
    procedure :: MaximumStep
    procedure :: CheckDirection
    procedure :: FDJAC
end type FuncBase

contains
REAL (KIND = F) Function Func(X)
    REAL (KIND = F), INTENT(IN) :: X

    Func = 0.0_F
End Function Func
...

 

The compiler complains bitterly "error #8262: For a type-bound procedure that has the PASS binding attribute, the first dummy argument must have the same declared type as the type being defined. "  I am obviously lost with this message conveying no information to me.

0 Kudos
Steven_L_Intel1
Employee
2,746 Views

When you have a type-bound procedure - that is, a procedure named after the CONTAINS in a type - the default is that the first argument to the routine is the derived type variable you used for the reference. So let's say you had a variable of type FuncBase named Z. If you call Z%Func(), there is an implicit first argument to Func of Z. That means you have to declare Func as having a first argument of TYPE(FuncBase) (or CLASS(FuncBase)). If you don't want that, you can add NOPASS to the procedure declaration in the type, but then you lose some of the object-orientedness of it.

0 Kudos
NotThatItMatters
Beginner
2,746 Views

Thank you Steve.  I noted that when reading the examples roughly five minutes after posting.  I have now rigged a "this" argument to the beginning of each argument list, being declared as 

class(FuncBase)

 and everything is compiling okay aside from warnings about routines where arguments are not used.  In essence I am trying to build prototypes for the subclasses which would actively implement those routines.  I am assuming this is the way to implement.

0 Kudos
Steven_L_Intel1
Employee
2,746 Views

Yes, that's right.

0 Kudos
jimdempseyatthecove
Honored Contributor III
2,746 Views

Steve,

Do you know why the Fortran standards committee did not choose to make the "this" arg implicit? (like most other OO languages)

The compiler can currently disambiguate name spaces in a hierarchy (ASSOCIATE, procedure, USE, COMMON). Then why not extend to member of type/class?

Jim Dempsey

0 Kudos
Steven_L_Intel1
Employee
2,746 Views

I wasn't on the committee in the F2003 timeframe. Remember that the actual function is just an ordinary function that can be called directly. The compiler has no idea about implicit arguments and can be external. You can say NOPASS in the type and get no "this" argument and you can put that argument elsewhere in the argument list if you like.

0 Kudos
Craig_Dedo
New Contributor I
2,746 Views

jimdempseyatthecove wrote:

Steve,

Do you know why the Fortran standards committee did not choose to make the "this" arg implicit? (like most other OO languages)

The compiler can currently disambiguate name spaces in a hierarchy (ASSOCIATE, procedure, USE, COMMON). Then why not extend to member of type/class?

Jim Dempsey

I was on the Fortran Standard Committee from November 1993 through November 2002.  This included all of the time that the OOP features were developed and implemented.  Malcolm Cohen of the Numerical Algorithms Group (NAG) headed up the design of the OOP features.

My memory is not complete, but the general approach of designing any new features in Fortran is to make them as upwardly compatible with existing features as possible.  This includes not only syntax and semantics but the general mental model as well.  Up until the time of OOP, the standard required that all procedure arguments be explicit.  If a type-bound procedure (TBP) had an implicit argument, this would have been a discontinuity in the mental model.

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
2,746 Views

Craig,

Thanks for your input. Maybe you can answer this backwardsly compatible situation:

module FooBar
integer :: someVar
end module FooBar
...
subroutine FooFoo
USE FooBar
...
someVar = 1234 ! someVar is in scope and thus requires no decoration or required dummy

The contains functions/subroutines could have easily extended upon the USE... scoping rules for accessing member variables. Procedure contained functions/subroutines do this.

BTW you do realize that the scoping rules are applied to the contains functions/subroutines ("member functions") themselves.

Jim Dempsey
 

0 Kudos
Craig_Dedo
New Contributor I
2,746 Views

jimdempseyatthecove wrote:

Do you know why the Fortran standards committee did not choose to make the "this" arg implicit? (like most other OO languages)

Yesterday afternoon I posted Jim Dempsey's question on the Fortran Standards Committee's mailing list.  Yesterday evening Malcolm Cohen provided the following answer. 

[Begin Malcolm Cohen answer]

Yes.

1. As noted in the question itself, not all other OO languages have an implicit "this" arg.

2. Like other OO languages, the "this" arg is implicit at the call site - it is only in the procedure that it is not implicit.

3. At the time, the following (already noted by others) were indeed factors in the decision:

(a) making "this" a reserved variable name would be a complete nonstarter as far as Fortran is concerned since we do not have reserved keywords at all;

(b) it is nice to be able to call it what you like;

(c) it is desirable to be able to specify other attributes;

(d) it enables use of the same procedure for multiple types when appropriate.

I would say that (a) and (b) were more significant than (c) or (d).

4. It enables use of ordinary procedures to implement these, instead of having to invent some kind of new "magic" procedure with special syntax.  We already have enough different kinds of procedures...

5. It enables implicit object passing for a non-initial argument, giving us type-bound operators and assignment where the derived type in question is the second operand.  Yes you can define all your overloading outside the type using INTERFACE blocks, but then type-bound assignment is especially important for avoiding the accidental loss of defined assignment that is possible with INTERFACE ASSIGNMENT(=) and careless use of the ONLY clause on a USE statement.

6. In my opinion, the overhead of having to declare the passed-object dummy is totally insignificant compared with the clarity it gives.  The procedure is just a normal procedure following the normal rules and the passed-object dummy is (inside the procedure) just a normal dummy argument.  Nothing complicated to get confused by.

There are certainly design decisions in F2003 that I regret, but this is not one of them.

[End of Malcolm Cohen answer]

Hope this helps.

0 Kudos
FortranFan
Honored Contributor III
2,746 Views

This is extremely helpful - Thank you much, Craig.

I agree with the overall assessment: I find Fortran 2003 design on this OO aspect consistent with the base language construct while also being quite flexible - great job by the standards creators, especially considering all the constraints and differing opinions that they would have encountered.

0 Kudos
NotThatItMatters
Beginner
2,746 Views

Okay, now that I "have" a class structure, I am having trouble "using" it.  I attempt to run the code, and get the nebulous "Program Exception, Access Violation" error.  According to the traceback, the error occurs with a call to

Call FP%Set_WellData(N, WELL_SET)

 

Routine 

Set_WellData

is of 

type(FuncBase)

where the object 

FP

is of 

type(FuncPressure)

.  

type, extends(FuncBase) :: FuncPressure

 

I am confused by the error.

0 Kudos
FortranFan
Honored Contributor III
2,746 Views

NotThatItMatters wrote:

Okay, now that I "have" a class structure, I am having trouble "using" it.  I attempt to run the code, and get the nebulous "Program Exception, Access Violation" error.  According to the traceback, the error occurs with a call to

Call FP%Set_WellData(N, WELL_SET)

 

Routine

Set_WellData

is of

type(FuncBase)

where the object

FP

is of

type(FuncPressure)

.

type, extends(FuncBase) :: FuncPressure

 

I am confused by the error.

 

Perhaps others can make more sense out of this error, but I would need a lot more detail to figure out what is going on.  I use type-bound procedures ("class structures" as you call them) extensively and I've never come across such an error.

Can you post your complete code, or if you cannot do that, then create a simple, generic example that reproduces the problem?

If you can't provide reproducible code, then refer to Dr. Fortran's blog on many books that give example code for type-bound procedures - try to use these examples and see if you can get them to work.  You can then adapt these examples to your situation.

0 Kudos
NotThatItMatters
Beginner
2,746 Views

Perhaps it is best if I could explain what I did to FIX it.  This might seem insanely obvious, but I am only learning Fortran OOP at present.  The problem lies between the declaration

type (FuncPressure) :: FP

and the declaration

class (FuncPressure), pointer :: FP

If I were in another language, I would assume the second declaration does not instantiate anything whereas the first does.  Well, guess what, this is how Fortran works.  I just had seen so many examples which used the class pointer that I was blinded to the underlying idea.

I am sorry for wasting your time.

0 Kudos
FortranFan
Honored Contributor III
2,746 Views

Yes, CLASS has a specific meaning in Fortran in relation to a polymorphic type.  It is not to be confused with class terminology used in other OO languages such as Java or Microsoft's .NET languages such as C#, Visual Basic, etc.

0 Kudos
Reply