Fortran 2000 Wish List

Even though Fortran 90 is not object-oriented, OOP is still possible although less automatic than with a fully object-oriented language. If it is decided not to make Fortran 2000 fully object-oriented, the following list of features would make OOP easier in Fortran 90 than it is now.

I. Automatic interfaces

In OOP, it is very common to overload function names in different classes to support polymorphism. This is possible in Fortran 90 with the interface statement, but in constructing a class, one may very well end up overloading every function name in a module, so that a substantial part of the class definition consists of interface statements. One also needs lots of private names for procedures which are needed only to construct the interface, and are subsequently thrown away. OOP in Fortran 90 would be much more streamlined, if interface attributes for procedures in modules could be supported, such as:

      interface, subroutine procedure_name(arguments)

which would be equivalent to:

      private :: dummy_procedure_name
      interface procedure_name
         module procedure dummy_procedure_name
      end interface
      subroutine dummy_procedure_name(arguments)

II. Overloadable array subsection operators:

Fortran 90 has a very powerful subsection operator (i:j:k), which works on arrays, such as:

      real, dimension(20) :: a
      print *, a(1:10:2)

This operator even works with arrays of derived type:

      type (something), dimension(20) :: b
      print *, b(1:10:2)

However, it will not work with derived types which contain pointers to arrays. These are useful if one needs to specialize arrays in some way. For example, if one defines:

      type something_else
         real, dimension(:), pointer :: ptr
         integer :: special_attribute
      end type
      type (something_else) :: special_array

one can refer to:

      special_array%ptr(1:10:2)

but not to:

      special_array(1:10:2)

C++ has subscript operators [] for this purpose, which are primitive versions of subsection operators (see, e.g, Lippman's C++ Primer, pp. 54-55).

Such a type is useful, for example, in describing a collection of particles, where a pointer to the particle coordinates are stored along with particle descriptors such as charge and mass. Since I would like to encapsulate (make private) the components of something_else, it would be useful to be able to say:

      special_array(1:10:2)

and define that operation to mean:

      special_array%ptr(1:10:2)

What I have in mind here is allowing user defined procedures to be equated to the operator '()'. This would be similar to how the multiply '*' operator is overloaded. In other words, I might have something like:

      interface operator (())
         module procedure do_something
      end interface
      contains
         function do_something(a,i,j,k) result(r)
         type (something_else) :: a, r
         integer :: i, j, k
         r%ptr = a%ptr(i:j:k)
         r%special_attribute = a%special_attribute
         end function do_something

As pointed out by James B. White III, however, the fact that array syntax exists for arrays of derived types (and presumably could not be redefined), leads to some syntactical difficulties. For example, how does one refer to a subsection of an element:

      type (something_else) :: array_of_special_arrays(10)
      array_of_special_arrays(1)(i:j:k)

Or a subsection of a subsection:

      array_of_special_arrays(l:m:n)(i:j:k)

Things get even more complicated in multiple dimensions. Without such a feature, it is very clumsy to build a class of specialized arrays. In C++ this is reasonably straightforward since the subscript operators are primitive. But Fortran90 has a powerful array syntax, and incorporating this will take some care.

III. Protected status for names in modules

Currently, names of procedures and derived types which are public in one module can be used by a second module and then made private to anyone using the second module. This allows a group of modules to gain access to names of procedures and derived types, yet deny access to program units outside this group. C++ has the protected category available for this purpose. This is possible in Fortran 90, but requires the programmer to list every name in the module individually. This would be much more simple, if the following statements were possible:

      use module_name
      private :: module_name

which would means that every name in the module is private.

Emulation of protected status is not possible, however, for components of a derived type. If they are public in the first module, they are public forever (unless the type name itself is made private). It is useful for efficiency reasons to allow a group of related modules to gain access to components. But for program safety and encapsulation one does not want universal access. Thus if the components of "something" are public in one module:

      type something
         real :: x
      end type

then a second module which uses the first could do something like:

         private, components :: something

which leaves the name "something" public, but its components are now private.

The following features are not related to OOP, but would nevertheless be convenient.

IV. Easier suppression of Carriage control:

Allow either Print *, or Write (*,*) to suppress carriage return. Currently to suppress carriage returns one must use the advance='no' specifier, which requires a format. I preferred the '$' fortran77 extension to what now exists.

V. Allocatable character lengths:

It would be nice to have the length of characters determined at run time.

      character*(:) c
      allocate(c(len=4))

VI. Permit Initialization of character array with trailing blanks:

The following is illegal:

      character*2, dimension(2) :: d = (/'22','3'/)

The only way to do this currently is to add trailing blanks:

      character*2, dimension(2) :: d = (/'22','3 '/)

It is a nuisance to add trailing blanks all over the place.

UP