Object-oriented programming in Fortran 2000

Dr W.W. Schulz (wws20@cus.cam.ac.uk)
Tue, 10 Mar 1998 10:52:21 +0000 (GMT)

Object-oriented Programming will be a new feature in Fortran 2000.

The Fortran J3 committee is currently working on drafting a proposal
and is coming closer to a complete draft.
I am somewhat concerned about the features proposed and those lacking
and would like to stimulate some discussion on this topic before any
real impact from users on the design is practically impossible.

OOP consists mainly of three major pillars though definitions here
vary somewhat in the literature and among practitioners.

1. Data abstraction and encapsulation
2. Inheritance
3. Polymorphism (incl. dynamic binding)

In my definitions and prescriptions of these concepts I start from the
premise that OOP requires usually more work to design the code than
traditional procedural programming and that it will be overwhelmingly
used in codes that are large (10K's of lines) and meant to last for some
time. Extending and maintaining the code is therefore a concern to the
programmer from the very beginning of the project.
The features of OOP supported by the language should reflect these concerns
directly and e.g. provide default behaviour that is in line with these
concerns.
In my view F90 is rather permissive from this perspective, partially for
reasons of compatility, but some are not, .e.g. IMPLICIT NONE is not
default, PUBLIC default for MODULE and TYPE components.
New features do not have to continue in this way but rather take a
more cautious attitude and support the programmer in this respect.

Some links to relevant literature follow at the end for interested readers.

To 1.
A higher level language strives to model real-world problem (real
in rather general sense of research and application) by using
constructs called objects that are closer to the problem and less
close to the computer. F90 has given us a taste of it with derived
data types. To work well with objects their internal details should
be encapsulated, that is hidden and only accessible through a well
defined interface (ie. procedures).
Reasons are that this is better for maintenance of large codes since
keeping the interface stable is usually rather easy. Secondly, the
internal variables of an object are interdependent so that changing
one variable directly leaves the object in an inconsistent state
leading to errors later on that are hard to debug.

To 2.
Single inheritance itself is not very difficult, neither in understanding nor
in implementing, multiple inheritance is more difficult but can be done in a
satisfactory manner. Some minor problems arise in connection with 1. but
are not difficult to handle and to a much larger degree with polymorphism.

To 3.
Polymorphism is a very powerful way of using more abstract programming
but it also brings a huge bag of problems, the most important one is
the question of static type checking.
Without going in to much detail, static type checking means that the
compiler checks every expression and statement for validity. This is
comparatively easy in Fortran 90 and other languages since every variable
has exactly one type and the checks can be done. Polymorphic objects can
have different types at run-time so type-checking becomes much more difficult.

In my view Fortran 2000 should be statically checked since this alerts
the programmer much earlier to mistakes and errors, reduces time spent
on checking at run-time and allows for optimisations at compile time,
all important reasons for having it.

The problem is that static checking must be rather pessimistic
(or conservative) and hence restricts inheritance and polymorphism.
Some examples are very well known in the literature
Some languages try to be safe (Java, C++ with some holes however in items
1. and 3.) but are too restrictive while others give up some safety for
more flexibility (Eiffel, Beta).
Since this topic is so important research is very active and recently some
better versions have been proposed. Fortran 2000 should take advantage of
it.

4. Genericity (generic or parametric types)
Not listed above but it is an important topic and some versions of OOP allow
for it in a very natural way. Not implementing it would seriously hamper a
modern version of Fortran.
Anybody who wanted to implement some modern codes like linked lists, or
even write a more general version of an old problem like sorting will
appreciate the usefulness of genericity.
As an example follows my version of quicksort at the end.
but it is written as a generic one, note that one only needs a "lessequal"
operator defined for the type T as indicated in the [] clause.
Since this kind of general programming comes quite easily in some forms of
OOP I don't see why it should be omitted, maybe not in the module form as
below (since that would require a bit more work) but certainly in the context
of OOP.

This does not refer to the parametrized TYPEs currently under work which do
not allow a type to a variable in the sense above but allow to set KIND and
DIMENSION of TYPE components.

5. Libraries based on OOP features
Without OOP and genericity the building of an efficient and portable library
of standard data structures like lists, trees, etc is not possible due to the
lack of code re-use features. This is already becoming a handicap for Fortran
users and does not bode well for the future of Fortran.

The current proposal by J3 should, in my view, be improved to form much stronger
and flexible OOP features esp. on items 1. and 3. and remove the lack of 4.

I am concerned for several reasons,

a) OOP will appear in 2002/3 at the earliest,

b) a rather minimal version of OOP denies Fortran'ers access to the real power
of OOP enjoyed by others,

c) provides little competition to C++ and the like,
esp. in the light that new OOP languages provide better and more efficient
C/C++ interfaces, ie. access to fast numerical libraries, and extensive
libraries for other purposes

d) any nice additions (assertions as in Eiffel, etc) are not even talked about
and have to wait for even more years

e) without a larger picture of where OOP is right now (see other languages)
and striving for at least the major features in a well-designed way the
proposal for OOP is in definite danger of being too little too late.

HOWEVER, if Fortran takes a decisive and bold step towards OOP and provides
OOP besides procedural programming with a strong and simple syntax, Fortran
would be in a good position for the next years.

Looking forward to some replies,
WWS
-----------------------------------------------------------------------
| Werner W Schulz |
| Dept of Chemistry email: wws20@cam.ac.uk |
| University of Cambridge Phone: (+44) (0)1223 336 502 |
| Lensfield Road Secretary: 1223 336 338 |
| Cambridge CB2 1EW Fax: 1223 336 536 |
| United Kingdom WWW: |
-----------------------------------------------------------------------

Literature (Webography):

Current Fortran 2000 status can be viewed at
http://www.ionet.net/~jwagener/j3/index.html
On OOP see especially papers
97-196r2 and 97-230 plus updates 98-133,136,137 as Committee papers
and alternatives 98-109, 98-108
(follow FTP access to J3 document repository, then year then 98 or 97)

K Bruce: several papers, see Recent Papers at
http://www.cs.williams.edu/~kim/
especially: On binary methods
Typing in object-oriented languages: Achieving
expressiveness and safety,

D Shang: Are Cows Animals?
http://www.sigs.com/publications/docs/oc/9601/oc9601.c.shang.html

B Meyer: Static typing and other mysteries of life
http://www.sigs.com/publications/docs/oc/9601/oc9601.c.meyer.html

_________________________________________________________________________
Generic QuickSort Example:
MODULE WWS_Sort
Copyright WW Schulz, Dept of Chemistry, U Cambridge 1997
PRIVATE
PUBLIC :: QuickSort
RECURSIVE SUBROUTINE QuickSort[T has "<=" ]( A )

T, INTENT(IN OUT) :: A(:)
Integer(int4) :: l,r,q
INTRINSIC LBOUND, UBOUND

l = LBOUND( A, DIM=1 )
r = UBOUND( A, DIM=1 )

DO ; IF( l>=r ) EXIT
CALL Int_Partition( A(l:r), q )
q = q +l -1
IF( q-l <= r-q ) THEN
CALL Int_QuickSort4( A(l:q) )
l = q +1
ELSE
CALL Int_QuickSort4( A(q:r) )
r = q
END IF
END DO

RETURN
END SUBROUTINE QuickSort
SUBROUTINE Partition( A, q )

T, INTENT(IN OUT) :: A(:)
Integer(int4), INTENT(OUT) :: q
Integer(int4) :: i,j
T, :: x, Swap
INTRINSIC LBOUND, UBOUND

i = LBOUND(A,DIM=1) -1
j = UBOUND(A,DIM=1) +1
x = A(i+1)
While_Loop: DO
DO ; i = i+1 ; IF( x<=A(i) ) EXIT
END DO

DO ; j = j-1 ; IF( A(j)<=x ) EXIT
END DO

IF( i<j ) THEN
Swap = A(i)
A(i) = A(j)
A(j) = Swap
ELSE
q = j
EXIT While_Loop
END IF
END DO While_Loop
RETURN
END SUBROUTINE Partition
END MODULE WWS_Sort

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%