ISO/IEC JTC1/SC22/WG5/N1238 Date: 07-jan-97 From: Manuela Zuern To: WG5 Subject: Report of WG5 data electronic subgroup References: WG5/N1189, WG5/N1215, x3j3/96-172 This subgroup report has been split in the following parts: Table of contents ================= I. Introduction II. List of Requirements for Better Data Abstraction in Fortran 2000 III. Specification of Some Requirements of the Data Subgroup IV. Priority Order of Requirements (Voting results) V. Comments on Requirements of Category-1 and Category-3 VI. Comments on Requirements of Category-2 ============================================================================= ============================================================================= I. Introduction At the last meeting in Dresden, WG5 built up several electronic subgroups to identify requirements for Fortran 2000, one of them concerning features for high quality data abstraction and user extensibility. Some requirements have been identified by WG5 and the /data subgroup to belong to better data abstraction facilities and the implementation of OO techniques. The requirements have been split into the following 3 categories 1. Requirements to complete existing data abstraction facilities 2. Requirements for better data abstraction and OO features 3. Other requirements concerning data abstraction The subgroup added a few requirements to those listed in the repository. Explanations to those additional requirements have been listed in an additional /data requirements list (part III of the report). All requirements are listed in part II of this report. (List of Requirements for Better Data Abstraction in Fortran 2000). This list contains the references data-E1 - data-E4. There have been votes on requirements and subjects to get a priority order. The voting results are listed in part IV of this paper. Parts V and VI contain individual comments on the votes of category-1 / category-3 and category-2 items. ============================================================================= ============================================================================= II. List of Requirements for Better Data Abstraction in Fortran 2000 -------------------------------------------------------------------- Some requirements have been identified by WG5 and the /data subgroup to belong to better data abstraction facilities and the implementation of OO techniques. The requirements have been split into the following 3 categories 1. Requirements which complete existing data abstraction facilities 2. Requirements for better data abstraction and OO features 3. Other requirements concerning data abstraction All three categories identify requirements for Fortran 2000. ============================================================================= Table of contents 1. Completion of Data Abstraction Mechanisms ============================================ 1.1 Requirements in context with interface generalization --------------------------------------------------------- 1.1.1 Priority specification for defined operators 1.1.2 Overloading possibility for Pointer assignment 1.1.3 Renaming of in USE 1.1.4 Regularize Handling of Pointer Arguments 1.1.5 INTENT for pointers 1.1.6 Remove INTENT(IN) requirement for OPERATOR, ASSIGNMENT 1.1.7 Intrinsic and User-defined Specific and Generic Names 1.1.8 Operators for more than two arguments 1.1.9 Aliasing Type Definitions 1.1.10 Allow s as actual arguments 1.1.11 Consider an array as a single object; give POINTER attribute to array valued function results 1.1.12 Develop a template/functor feature for the language 1.2 Expression Classification ----------------------------- 1.2.1 Object Oriented Programming 1.3 Input/Output ---------------- 1.3.1 Derived Type I/O 1.4 Requirements in context with data visibility ------------------------------------------------ 1.4.1 Allow PUBLIC entities of PRIVATE type 1.4.2 Allow a PUBLIC operator USEd in another module to be made PRIVATE for further use. 1.4.3 Separate specification of the access attributes of a derived type 2. Better Data Abstraction and Object Oriented Features ======================================================= 2.1 Constructor & Destructor ---------------------------- 2.1.1 Requirement for Cleaner (and Producer) in Fortran 90 2.1.2 Constructors and destructors 2.2 Relation of data and procedures (defining objects, methods) ----------------------------------------- 2.2.1 Procedure variables 2.2.2 Pointers to Procedures 2.2.3 A Proposal for OO Features in Fortran 2.3 Inheritance --------------- 2.3.1 Class inheritance (and dynamic binding polymorphism) 2.3.2 A Proposal for OO Features in Fortran 2.4 Information Hiding ---------------------- 2.4.1 Additional Visibility Attribute 2.4.2 Additional Visibility Attribute for Classes 2.5 Polymorphism ---------------- 2.5.1 (Class inheritance and) dynamic binding polymorphism 2.5.2 A Proposal for OO Features in Fortran 3. General Data Abstraction Features ==================================== 3.1 Remove name class irregularities 3.2 Regularize KIND parametrization intrinsics 3.3 Array Components of Array Structures 3.4 Extend ALLOCATE to specify non-KIND type parameters ============================================================================= ============================================================================= Category 1. Completion of Data Abstraction Mechanisms ===================================================== This category mainly collects requirements which are extensions and completions on existing data abstraction facilities already defined in Fortran 95. 1.1 Requirements in Context with Interface Generalization ========================================================= 1.1.1 Priority specification for defined operators References : data-E1 X3J3 Status: A similar requirement has been submitted to X3J3 (#088 : User specified precedence) but no work has been done on it yet. The Fortran 90 (and 95) standard allows the user to choose a new name for an operator, but prohibits the specification of its priority (precedence, binding strength) in expressions. The current standard imposes highest priority for unary and lowest priority for binary defined operators without regard to the intended semantics. The current situation is unsatisfactory because the priority imposed by the standard is rarely the one the application calls for and thus the mechanism by which new operators are defined is clearly incomplete. This forces the user to employ extra parentheses (which are mostly superfluous in the user's intuitive hand-notation) to control precedence in all but the most trivial expressions involving defined operators or to abandon the use of defined operators altogether. From the formal language point of view, burdening every "user" (i.e. expression) of a feature with superfluous work (or syntax) instead of solving the problem at its root (i.e. at the point of definition of an operator) violates the principle of locality as well as making the usage of defined operators very error-prone and counterintuitive. The functionality is to allow the specification of a priority for defined operators that is different from the predefined priority. All overloads of a defined operator must have the same priority, that is, the priority is associated with the operator name. The priority levels for unary operators should be reserved for unary operators, the other priority levels for binary operators. Estimated Impact: Medium impact on compilers (may require generalization of symbol/operator table) no impact on efficiency huge impact on user-friendliness of defined operators. This requirement does not affect existing programs. 1.1.2 Overloading possibility for Pointer assignment References : ISO/IECJTC1/SC22/WG5 N1189 #84 Using pointers and especially pointer assignments in large applications often causes problems with managing the targets. A target which has been explicitly allocated has got to be destroyed if no pointer is going to be related with the target anymore. It is not the intention of abstraction to increase and decrease target links before and after pointer assignment statements, but rather to hide this management in a procedure defining an overloaded pointer assignment, because this management belongs directly to the pointer assignment. The interface for the pointer assignment overloading is very natural and Fortran like proposed as interface assignment(=>) ... end interface 1.1.3 Renaming of in USE References : ISO/IECJTC1/SC22/WG5 N1189 #41 X3J3 Status : ??? (M.15, ???) Extend the renaming rules for USE which allow renaming of entities in the USEd module to also allow the renaming of a defined operator. For (also) OO technologies this e.g. avoids name conflicts with reused modules and gives the possibility to rename operators which differ slightly in their functionalities. Example: USE geometry, OPERATOR(.max_norm.) => OPERATOR(.dist.) The requirement affects only the form of the USE statement. Compile-time effects, no impact on program execution and neglectable impact on compilation speed 1.1.4 Regularize Handling of Pointer Arguments References : ISO/IECJTC1/SC22/WG5 N1189 #44 X3J3 Status : nearly finished (M.2, R.Maine) Treat pointer dummy arguments more like other dummy arguments to reduce surprises and make operations involving pointers easier to express. discussion on it. 1.1.5 INTENT for pointers References : ISO/IECJTC1/SC22/WG5 N1189 #44a X3J3 Status : nearly finished (M.2, R.Maine) Allow pointer arguments to have the INTENT attribute which refers to the pointer association status. 1.1.6 Remove INTENT(IN) requirement for OPERATOR, ASSIGNMENT References : ISO/IECJTC1/SC22/WG5 N1189 #56 F90/95 requires that dummy arguments for OPERATOR specific procedures shall be specified with INTENT(IN). For ASSIGNMENT specific procedures, the first dummy argument shall have INTENT(OUT) or INTENT(INOUT), the second dummy argument shall have INTENT(IN). Remove the above INTENT(IN) requirements, but still require that the actual INTENT shall be specified. The Impact is medium for the processor. There is some great improvement for applications that are not elegantly expressable with the INTENT(IN) requirement in effect. No Impact on old portable F95 programs. 1.1.7 Intrinsic and User-defined Specific and Generic Names References : ISO/IECJTC1/SC22/WG5 N1189 #59 X3J3 Status : already in F95, (M.11, K. Hirchert) Permit the specific name of a user-defined procedure to be passed as an actual argument even if it is the same as the generic name, just as is permitted in Fortran 77 and Fortran 90 for intrinsic functions 1.1.8 Operators for more than two arguments References : ISO/IECJTC1/SC22/WG5 N1189 #85 Allow to define operators for more than two arguments, to give a user the possibility to write his code in a more natural way. e.g. * to define a tensor a .[. x,y,z .]. * to create a matrix out of a set of vectors A = .[. v1,v2,v3,v4 .]. * Lee brackets .<. A,B .>. Interface specification could look like the following interface operator(.[.#.].) module procedure function set_of_vectors end interface function set_of_vectors(v1,v2.v3.v4) result(matrix) ... end function set_of_vectors 1.1.9 Aliasing Type Definitions References : ISO/IECJTC1/SC22/WG5 N1189 #11 Give the ability for programmers to use one type name as an alias for another. Example: Type Float :: ALIAS = real(stnd) type(float) :: a,b,c Impact on software developers could be significant as this could represent a notable simplification. Impact on existing programs should be nonexistent, since the syntax and semantics proposed are not currently permitted. Impact on compilers is probably not large. They will simply have to recognize that one type name is simply a synonym for some other type name. 1.1.10 Allow s as actual arguments References : ISO/IECJTC1/SC22/WG5 N1189 #54 Allow s (R1207) to be used as actual arguments if the interface of the called procedure and the interface of the corresponding dummy procedure is explicit. Actual arguments associated with dummy procedures need not be specific procedures in this case. It is good programming style to give specific procedures for a the PRIVATE attribute. Currently, such procedures cannot be passed as actual arguments. Impact is low. All information is known by the compiler, therefore resolving the is possible at the caller side. No impact on existing portable F95 programs. 1.1.11 Consider an array as a single object; give POINTER attribute to array valued function results References : ISO/IECJTC1/SC22/WG5 N1189 #96 Possibility to consider an array as a single whole object, e.g. in instrinsic function calls. No impact on existing programs. 1.1.12 Develop a template/functor feature for the language References : data-E3 1.2 Expression Classification ============================= 1.2.1 Object Oriented Programming (New classification of expressions) References : ISO/IECJTC1/SC22/WG5 N1189 #18 This requirement allows the realization of the object oriented model in Fortran by a new classification of expressions in the following three classes * KIND or static expressions that involve primaries that are literal constants whose values are determined by static expressions, possibly involving intrinsic operators, and a restricted set of intrinsic functions * Initialization expressions that involve primaries that are static expressions, accessible explicit procedures that are proper functions * Specification expressions that involve any data-object or proper function that is accessible and defined at the time of invocation of the program or procedure. (proper function would be a function whose value was uniquely determined by its arguments and which had no side effects.) 1.3 Input/Output ================ 1.3.1 Derived Type I/O References : ISO/IECJTC1/SC22/WG5 N1189 #17 X3J3 Status: being done by X3J3 (R.1, R.Bleikamp) Extends instrinsic I/O syntax to cover derived types. 1.4 Requirements in context with data visibility ================================================ 1.4.1 Allow PUBLIC entities of PRIVATE type References : ISO/IECJTC1/SC22/WG5 N1189 #75 Remove the restrictions in the standard that require (1) for PUBLIC module variables and parameters of derived type that the type is defined as PUBLIC; (2) for components of a PUBLIC derived type definition in a module, that the component type must be intrinsic or defined as PUBLIC; (3) PUBLIC module functions of derived type must be of a type defined as PUBLIC; and (4) derived-type dummy arguments of a PUBLIC module procedure must be of a type defined as PUBLIC Small effect on standard. No anticipated effect on other suggested features.. Little impact in compilers. No significant effect on compiler speed. No effect on execution speed. 1.4.2 Allow a PUBLIC operator USEd in a module to be made PRIVATE for further use. References : Extension of ISO/IECJTC1/SC22/WG5 N1189 #74; data-E2 An operator .myop., which has been defined PUBLIC in module A for the datatype ATYPE and is USEd (and extended) in module B for the datatype BTYPE should be redefinable in its visibility. Therefore a module using module B could have public access to the operator .myop. defined for BTYPE but private (->no) access to the operator .myop. defined for ATYPE. 1.4.3 Separate specification of the access attributes of a derived type References : data-E4 The actual Fortran Standard does not allow a separate specification of the accessibility of derived type components. In strict object oriented programming one would always access derived type components via an interface. But as Fortran is not going to be a pure object oriented language but rather a language for data abstraction with object oriented features, it is very important to support the separate accessibility specification. ===================================================================== ===================================================================== Category 2: Better Data Abstraction and Object Oriented Features ================================================================ This category contains main subjects of Object Orientation and proposals of the repository which have been made for the certain subjects to get an overview on implementation suggestions. One main paper which belongs into this category is paper X3J3/96-172, written by John Cuthbertson after the last X3J3 meeting nov 96. It covers most of the subjects listed below and some additional. 2.1 Constructor & Destructor ============================ Each allocation of a data object must have a corresponding deallocation of the data object. Sometimes this deallocation mechanism cannot be invoked by the programmer, e.g. in statements with function results containing pointers which are used as further arguments like in a5 = fu1(a1, fu2(a2, fu3(a3,a4))) If the code of fu2 and fu3 cannot be accessed (e.g. if library procedures are used) there is no possibility for the user to deallocate their results which may include pointer targets. For further explanation see ISO/IECJTC1/SC22/WG5 N1187. This kind of object destruction can be done by a destructor. A destructor is an operation that destroys an instance including maintaining referential integrity and deallocation its associated memory. It is invoked implicitly. A constructor is an operation that constructs (i.e., instantiates) an instance, allocates memory to dynamic objects, creates the bindings to operations, and initializes the values of the properties. 2.1.1 Requirement for Cleaner (and Producer) in Fortran 90 (87) (Germany) References : ISO/IECJTC1/SC22/WG5 N1189 #87 ISO/IECJTC1/SC22/WG5 N1187 A cleaner is a destructor to destroy data when it is not needed anymore, after the end of its scope. 2.1.2 Constructors and destructors (89) (France) References : ISO/IECJTC1/SC22/WG5 N1189 #89 Supplement the ALLOCATE statement with a constructor capability and the DEALLOCATE statement with a destructor capability. 2.2 Relation of data and procedures (methods) (Declaration of Classes) ============================================= For object oriented programming it must be syntactically possible to identify an abstraction of a set of logically related instances that share the same or similar characteristics. Such an abstraction is defined to be a class. Therefore it must be possible to relate data directly with methods working on the data. Some kind of class clause which distinguishes a class from a derived type can be advantageous. 2.2.1 Procedure variables References : ISO/IECJTC1/SC22/WG5 N1189 #43 X3J3 Status: being done by X3J3 (R.3, R.Maine) Allow variables other than dummy arguments to refer to procedures. Example: (See Ref.) (4) Derived type function component (implicit interface) TYPE metric_space INTEGER :: dimensionality REAL, PROCEDURE :: metric ... END TYPE metric_space (5) Derived type subroutine component (implicit interface) TYPE user_command CHARACTER*10 :: keyword PROCEDURE :: action ... END TYPE user_command (7) Derived Type containing some functions 2.2.2 Pointers to Procedures References : ISO/IECJTC1/SC22/WG5 N1189 #43a X3J3 Status: being done by X3J3 (R.3, R.Maine) Provide pointers which are associated with procedures rather than variables 2.2.3 A Proposal for OO Features in Fortran References : X3J3/96-172 (includes both, Procedure variables and Pointers to Procedures) 2.3 Class Inheritance ===================== Inheritance is a mechanism that permits classes to share characteristics. Definition of derived classes is constructed in terms of one or more base classes. 2.3.1 Class inheritance (and dynamic binding polymorphism) (88) (France) References : ISO/IECJTC1/SC22/WG5 N1189 #88 ISO/IECJTC1/SC22/WG5 N1188 Requirement for two object-oriented meachanisms: class inheritance and dynamic binding polymorphism. The proposed extensions are borrowed from Ada 95 with a syntax more compatible with the Fortran culture => missing in this proposal are objects consisting of data AND methods, and therefore the possibility to inherit and override methods 2.3.2 A Proposal for OO Features in Fortran References : X3J3/96-172 2.4 Information Hiding ====================== Information hiding is the deliberate and enforced hiding of information like design decisions or implementation details from clients. The visible parts of a class describe the class interface. Fortran 90 already provides two visibility attributes, PUBLIC and PRIVATE. At least if some kind of inheritance is included, it can be helpful to have one or more kinds of additional visibility attributes. Demands like requirement 1.4.2 could also be solved by additional visibility attributes 2.4.1 Additional Visibility Attribute References : ISO/IECJTC1/SC22/WG5 N1189 #74 Provide a third level of accessibility, between PRIVATE and PUBLIC, for module entities. This allows limited polymorphism. 2.4.2 Additional Visibility Attribute for Classes Reference : If some kind of inheritance is included, it is necessary to have an additional visibility attribute which allows access to an object of a class from objects of subclasses related through inheritance, but restricts access from objects outside the class (inheritance tree), which are not related somehow. 2.5 Polymorphism ================ Polymorphism is the ability of a single name to refer to different things having different forms. It is one of the most important aspects of object orientation. Some kinds of polymorphism are already included in the language, some more have been proposed to be implemented in the future standard revision. 2.5.1 (Class inheritance and) dynamic binding polymorphism (88) (France) References : ISO/IECJTC1/SC22/WG5 N1189 #88 ISO/IECJTC1/SC22/WG5 N1188 Requirement for two object-oriented meachanisms: class inheritance and dynamic binding polymorphism. The proposed extensions are borrowed from Ada 95 with a syntax more compatible with the Fortran culture 2.5.2 A Proposal for OO Features in Fortran References : X3J3/96-172 ===================================================================== ===================================================================== Category 3: General Data Abstraction Features ============================================= Requirements within this category stand on their own and are neither directly related to completion of existing data abstraction features nor to object oriented features, but still belong to the /data subgroup. 3.1 Remove name class irregularities References : ISO/IECJTC1/SC22/WG5 N1189 #15 Remove derived type names and construct names from the class of local entities 3.2 Regularize KIND parametrization intrinsics References : ISO/IECJTC1/SC22/WG5 N1189 #57 1. Introduce a SELECTED_LOGICAL_KIND(R) instrinsic function 2. SELECTED_INT_KIND and SELECTED_REAL_KIND operate with radix 10. Introduce an optional, default integer parameter RADIX to allow kind selection with different radix, like radix or radix (13.7.1) 3. Extend HUGE(X) for X of type character, with result characteristics default integer and result value (as used e.g. in 13.14.19 CHAR) 3.3 Array Components of Array Structures References : ISO/IECJTC1/SC22/WG5 N1189 #58 Treat array structures containing array components as higher-rank array objects; that is, remove the restriction against structure references containing more than one part-ref with non-zero rank. Interpret the shape of such a reference to be (/ C, P /), where P is the shape of the parent and C is the shape of the component. 3.4 Extend ALLOCATE to specify non-KIND type parameters References : ISO/IECJTC1/SC22/WG5 N1189 #72 Extend the ALLOCATE statement to allow specification of type parameters. Allow POINTER or ALLOCATABLE to be used with declaration forms used to "assume" type parameters. ============================================================================= ============================================================================= III. Specification of Some Requirements of the Data Subgroup: ============================================================================= Table of contents: data-E1 : Priority specification for defined operators data-E2 : Allow a PUBLIC operator USEd in another module to be made PRIVATE for further use. data-E3 : Develop a template/functor feature for the language data-E4 : Separate specification of the access attributes of a derived type ============================================================================= Number: data-E1 Title: Priority specification for defined operators Submitted By: DIN Status: For consideration References: Basic Functionality: Allow the specification of a priority for defined operators that is different from the predefined priority. All overloads of a defined operator must have the same priority, that is, the priority is associated with the operator name (see note below). The priority levels for unary operators, 1 (top), 4 (unary + and -), and 8 (.NOT.), should be reserved for unary operators, the other priority levels for binary operators. Although the set of priority levels (currently 12) could in principle be augmented, this currently seems to be a requirement in few applications. If the user does not specify the priority of an operator, the default rule as defined by the current standard applies which imposes highest priority for unary and lowest priority for binary defined operators. Associativity rules are not changed, i.e. a sequence of binary operators with the same priority is interpreted from left to right (with the exception of sequences of ** operators). Thus existing programs are not affected. There are several ways to enforce the requirement that an operator name must have only one priority associated with it. The simplest rule to understand and enforce is probably that within a given context (scoping unit), all visible overloads of an operator name must have the same priority. Rationale: The Fortran 90 (and 95) standard allows the user to choose a new name for an operator, but prohibits the specification of its priority (precedence, binding strength) in expressions. The current standard imposes highest priority for unary and lowest priority for binary defined operators without regard to the intended semantics. The current situation is unsatisfactory because the priority imposed by the standard is rarely the one the application calls for and thus the mechanism by which new operators are defined is clearly incomplete. This forces the user to employ extra parentheses (which are mostly superfluous in the user's intuitive hand-notation) to control precedence in all but the most trivial expressions involving defined operators or to abandon the use of defined operators altogether. >From the formal language point of view, burdening every "user" (i.e. expression) of a feature with superfluous work (or syntax) instead of solving the problem at its root (i.e. at the point of definition of an operator) violates the principle of locality as well as making the usage of defined operators very error-prone and counterintuitive. Priority must be a syntactic, not a semantic property of an operator, i.e. the expression tree must be uniquely determined solely by its SYNTAX. Thus it is mandatory that a priority be associated with an operator NAME (or SYMBOL) and not with a particular operator overload, i.e. all operators with the same name (symbol) must have the same priority. This rule is necessary to avoid the situation where an expression will only allow contradictory interpretations. To see this, consider the following example: INTERFACE OPERATOR ( .BINOP. ) PRIORITY ( + ) MODULE PROCEDURE ADDFUN END INTERFACE INTERFACE OPERATOR ( .BINOP. ) PRIORITY ( * ) MODULE PROCEDURE MULFUN1, MULFUN2 END INTERFACE CONTAINS REAL FUNCTION ADDFUN (x, y) INTEGER, INTENT(IN) :: x, y . . . END FUNCTION ADDFUN REAL FUNCTION MULFUN1 (x, y) INTEGER, INTENT(IN) :: x ; REAL, INTENT(IN) :: y . . . END FUNCTION MULFUN1 REAL FUNCTION MULFUN2 (x, y) REAL, INTENT(IN) :: x ; INTEGER, INTENT(IN) :: y . . . END FUNCTION MULFUN2 When these operators are used in an expression such as INTEGER :: A, B, C . . . . . . A .BINOP. B .BINOP. C in the absence of other overloads for the operator name .BINOP., both interpretations violate the specified priorities: . . . MULFUN1( A, ADDFUN(B, C) ) . . . MULFUN2( ADDFUN(A, B), C ) This problem is not restricted to multiple occurrences of the same operator name in an expression. Estimated Impact: Medium impact on compilers (may require generalization of symbol/operator table), no impact on efficiency, huge impact on user-friendliness of defined operators. Does not affect existing programs. Detailed Specification: History: A large amount of experience exists (or used to exist) in Algol 68 which featured user-defined operators with user-defined priorities. Several other languages such as Ada, PASCAL-XSC and FORTRAN-SC have similar features which, in some cases, have been in use for almost 20 years. ============================================================================= Number: data-E2 Title: Allow a PUBLIC operator USEd in another module to be made PRIVATE for further use. Status: For consideration Basic Functionality: Having a module called type_a_module MODULE type_a_module ! ! Exports TYPE(type_a) and OPERATOR(==) for type_a ! PRIVATE TYPE, PUBLIC :: type_a INTEGER :: brand END TYPE type_a PUBLIC :: OPERATOR(==) INTERFACE OPERATOR(==) MODULE PROCEDURE eq_type_a END INTERFACE ! OPERATOR(==) CONTAINS LOGICAL FUNCTION eq_type_a ( a, b ) TYPE(type_a), INTENT(IN) :: a, b eq_type_a = a%brand == b%brand END FUNCTION eq_type_a END MODULE type_a_module and a second module which USEs TYPE_A MODULE type_b_module ! ! Exports TYPE(type_b) and OPERATOR(==) for type_b ! Also exports OPERATOR(==) for type_b, which may be not intentional ! USE apples PRIVATE TYPE, PUBLIC :: type_b INTEGER :: brand END TYPE type_b PUBLIC :: OPERATOR(==) ! this always exports == for apples INTERFACE OPERATOR(==) MODULE PROCEDURE eq_type_b END INTERFACE ! OPERATOR(==) CONTAINS LOGICAL FUNCTION eq_type_b ( a, b ) TYPE(type_b), INTENT(IN) :: a, b eq_type_b = a%brand == b%brand END FUNCTION eq_type_b ! ... some private module procedures needing apples ... END MODULE type_b_module there is no possibility for TYPE_B *not* to export the '==' defined for TYPE_A if the '==' operator for TYPE_B has to be public. It is definitly no solution to move the USE statement for the TYPE_A module to the MODULE PROCEDUREs, because e.g. there could exist global module variables needing APPLES ... Allowing not to export any operator functionality for a public operator is very helpful in context with implementing different abstraction levels. ============================================================================= Number: data-E3 Title: Develop a template/functor feature for the language Status: For consideration Basic Functionality: While Fortran 90 greatly increased the flexibility of Fortran, there are numerous occasions where the language is not as flexible (polymorphic) as desired. Many languages have found it useful to include parametric polymorphism, e.g., "generics", "templates", or "Functor"s, where modules, types, or procedures are defined to operate for a variety of types of objects. Consider the following artificial example: TYPE A REAL :: val END TYPE TYPE B DOUBLE PRECISION :: val END TYPE TYPE C COMPLEX :: val END TYPE TYPE D INTEGER :: val END TYPE If the operator ">" is to be overloaded between every combination of the above types, separate procedures for each combination of types have got to be written TYPE(A) > TYPE(A) TYPE(A) > TYPE(B) TYPE(A) > TYPE(C) TYPE(A) > TYPE(D) TYPE(B) > TYPE(A) TYPE(B) > TYPE(B) TYPE(B) > TYPE(C) TYPE(B) > TYPE(D) ..... and so on It would be rather more convenient to be able to write ONE procedure and then be able to extend the interface such that the procedure will "work" for each combination of types. INTERFACE OPERATOR (">") LOGICAL FUNCTION Wibble(x,y) TYPE(A,B,C,D), INTENT(IN) :: x,y END FUNCTION Wibble END INTERFACE Thus Wibble would be automatically overloaded for all the combination of types. Please note that this is NOT proposed to be the adopted syntax, it is just used to demonstrate the point. An alternative syntax could be the one via FUNCTORs FUNCTOR WIBBLE(A, B) LOGICAL FUNCTION Wibble(x,y) TYPE(A), INTENT(IN) :: x TYPE(B), INTENT(IN) :: y WIBBLE = x.val > y.val END FUNCTION Wibble END FUNCTOR WIBBLE INTERFACE OPERATOR (">") LOGICAL FUNCTION Wibble1(x,y) = WIBBLE(A, A) LOGICAL FUNCTION Wibble2(x,y) = WIBBLE(A, B) LOGICAL FUNCTION Wibble3(x,y) = WIBBLE(B, A) LOGICAL FUNCTION Wibble4(x,y) = WIBBLE(A, D) LOGICAL FUNCTION Wibble5(x,y) = WIBBLE(D, A) LOGICAL FUNCTION Wibble6(x,y) = WIBBLE(B, B) LOGICAL FUNCTION Wibble7(x,y) = WIBBLE(B, D) LOGICAL FUNCTION Wibble8(x,y) = WIBBLE(D, B) LOGICAL FUNCTION Wibble9(x,y) = WIBBLE(D, D) END INTERFACE There are two means of implementing Functors, as either a form of typesafe macro, or as true generic procedures. It should be noted that C++ has found that templates, when used as typesafe macros, can be used to generate very efficient code in combination with iterators. ============================================================================= Number: data-E4 Title: Separate specification of the access attributes of a derived type Status: For consideration Basic Functionality: The actual Fortran Standard does not allow a separate specification of the accessibility of derived type components. Currently the components of PUBLIC types are either accessible when the module containing the type is used, the default, or none of them are accessible, if a PRIVATE statement is included in the type definition. This can lead to awkward or inefficient derived type implementations. The best example of this is a data object some of whose values should only be changed through the type interface, but other values can be safely modified by the user. The default does not guarantee consistent use of the interface. If a PRIVATE statement is included, then use of procedures must be used to access any component. It is difficult, in the second case, to optimize away the procedure overhead implied by the resulting semantics, and the creation of the procedure is an unnecessary burden on the programmer. In strict object oriented programming one would always access derived type components via an interface. But as Fortran is not going to be a pure object oriented language but rather a language for data abstraction with object oriented features, it is very important to support the separate accessibility specification. ============================================================================= ============================================================================= IV. Priority Order of Requirements To give the requirements a priority order there have been two votes on requirements, one on each single Category-1 and Category-3 item, the second one on subjects of Category-2 items. The requirements in Category-1 and Category-3 items are clear suggestions and therefore could be considered as they were, while the Category-2 items are mostly different suggestions for the implementation of the same thing. Therefore the vote on Category-2 items has been a vote on subjects rather than a vote on requirements to see what kind of object oriented features have the highest priority to be implemented in the next Fortran Standard. The Voting Results are listed below. For evaluation, priority points have been given to the individual votes and the average value has been determined. The Priority Points have been set as follows H (High Priority item) => 3 points M (Middle Priority item) => 2 points L (Low Priority item) => 1 point O (Omit the item) => 0 points N (no vote on this subject) => effect on the average value Voting Results Category-1 items =============================== Comments on this vote are listed in part V of the report Title Average Priority Value ----------------------------------------------------------------------------- 1.1.1 Operator Priorities 1.0 1.1.2 Overloading possibility for Pointer Assignment 1.3 1.1.3 Renaming of in USE 1.4 1.1.4 Regularize Handling of Pointer Arguments 1.4 (worked on by X3J3) 1.1.5 INTENT for pointers 1.7 (worked on by X3J3) 1.1.6 Remove INTENT(IN) requirement for OPERATOR, ASSIGNMENT 0.6 1.1.7 Intrinsic and User-defined Specific and Generic Names 0.8 (already in F95!) 1.1.8 Operators for more than two arguments 0.5 1.1.9 Aliasing Type Definitions 1.6 1.1.10 Allow s as actual arguments 0.8 1.1.11 Consider an array as a single object; give POINTER 0.6 attribute to array valued function results 1.1.12 Develop a template/functor feature for the language 1.2 1.2.1 Expression Clarification - Object Oriented Programming 1.4 1.3.1 Derived Type I/O 2.3 (worked on by X3J3) 1.4.1 Allow PUBLIC entities of PRIVATE type 1.2 1.4.2 Allow a PUBLIC operator USEd in a module to be made 0.9 PRIVATE for further use. 1.4.3 Separate specification of the access attributes of a 1.6 derived type Voting Results Category-2 subjects ================================== Comments on this vote are listed in part VI of the report Question Average Priority Value ----------------------------------------------------------------------------- Vote 1 Should a constructor and destructor be 1.9 implemented ? Vote 2 Should there be an extra clause like 'class' 1.5 or something similar to distinguish derived types from classes ? Vote 3 Should Single Class Inheritance be implemented ? 2.8 Vote 4 Should Multiple Class Inheritance be implemented ? 0.6 Vote 5 Do we need additional visibility attribute(s) 1.0 outside class relations ? Vote 6 Do we need additional visibility attribute(s) 1.4 for related classes ? Vote 7 Do we need dynamic binding for Fortran ? 2.1 Vote 8 If inheritance is implemented, should subroutines be 2.2 overridable ? Voting Results Category-3 items =============================== Comments on this vote are listed in part V of the report Title Average Priority Value ----------------------------------------------------------------------------- 3.1 Remove name class irregularities 1.2 3.2 Regularize KIND parametrization intrinsics 1.3 3.3 Array Components of Array Structures 1.0 3.4 Extend ALLOCATE to specify non-KIND type parameters 1.5 ============================================================================= ============================================================================= V. Comments on Requirements of Category-1 and Category-3 ========================================================= These are only comments in context with the votes, no further discussion has been considered. 1.1.1 Operator Priorities Christian Weber : I think this feature is necessary for the new interval operations. Dr. S. Morgan : Does not increase functionality and is somewhat controversial in that it impacts readability of code and potential for user error. IMO not worth the fight. Malcolm Cohen : Widely recognised as a big mistake (even by proponents of the languages that include it), this results in effectively every program being written in a different language. Manuela Zuern : Essential for any kind of object orientation is the regulation of the interface construction including the possibility for the user to specify the priorities of at least his own user defined operators. 1.1.2 Overloading possibility for Pointer assignment Dr. S. Morgan: Don't understand #84 description. Malcolm Cohen : Overloading pointer-assignment is completely pointless. One might as well overload the concept of argument association or EQUIVALENCE. Manuela Zuern : Essential for any kind of object orientation is the regulation of the interface construction including the possibility for the user to overload at least the pointer assignment, if not even more statements like 'allocate', 'print',... Using pointer assignments can cause problems with managing the targets. A target which has been explicitly allocated has got to be destroyed if no pointer is related with the target anymore. It is not the intention of abstraction to implement things like increasing and decreasing target links before and after pointer assignment statements, but rather to hide this management in a procedure defining an overloaded pointer assignment, because this management belongs directly to (in !) the pointer assignment. Example: type mytype integer :: link = 0 real,dimension(100000) :: values = 0. end type mytype type(mytype),pointer :: p1,p2,t,s allocate(t,s,p2) p1 => s p2 => t !* mark a p1 => t ... deallocate(p1) !* mark b * with statement in 'mark a', the allocated target for p2 cannot be accessed anymore. * with statement in 'mark b', the association status of the pointers p1,p2, and s is undefined The same pointer assignment including a management by a link counter could look like the following allocate(t,s,p2) t%link = t%link + 1 !* increase the link to '1' s%link = s%link + 1 !* increase the link to '1' p2%link = p2%link + 1 !* increase the link to '1' ... if (p1%link == 1) then !* p1 has already an allocated target deallocate(p1) nullify(p1) !* link counter is in data structure and therefore can not be !* decreased elseif (p1%link > 1) then p1%link = p1%link - 1 !* decrease number of links endif p1 => s; p1%link = p1%link + 1 !* increase number of links if (p2%link == 1) then !* p2 has already an allocated target deallocate(p2) nullify(p2) !* link counter is in data structure and therefore can not be !* decreased elseif (p2%link > 1) then p2%link = p2%link - 1 !* decrease number of links endif p2 => s; p2%link = p2%link + 1 !* increase number of links ... * The code explodes if such a necessary management is implemented * If the pointer assignment could be overloaded, at least the 'management steps' for the target around the pointer assignment could be hidden. (This also requires the INTENT for pointer arguments) interface assignment(=>) module procedure mytype_pointer_assign end interface subroutine mytype_pointer_assign(m1,m2) type(mytype),pointer,intent(in) :: m2 type(mytype),pointer,intent(inout) :: m1 if (m1%link == 1) then !* m1 already has an allocated target deallocate(m1) nullify(m1) elseif (m1%link > 1) then !* m1 shares a target with other pointers m1%link = m1%link - 1 !* decrease number of links endif m1 => m2; m1%link = m1%link + 1 !* increase number of links end subroutine mytype_pointer_assign * There is still a problem with increasing and decreasing links at the allocate and deallocate statements. Therefore it would indeed also be desirable to be able to overload statements like allocate, deallocate, nullify, ... 1.1.3 Renaming of in USE Jeanne T. Martin : Only user-defined operations Christian Weber : The renaming should be limited to user-defined names: intrinsic names should be excluded. Michael Hennecke : To reply to Malcolm's fear of .EQV. being renamed-out-of-the-program-unit, please replace ``'' by the more restrictive term `` or ''... Malcolm Cohen : The big problem here is what happens when you rename intrinsic operators (e.g., .EQV.). This "obviously" must render the intrinsic operations only accessible via their new name, and again, results in unreadable programs. ------ I do not have my standard at hand (I am at home), but assuming that this would forbid the renaming of any intrinsic operators (which it certainly looks to do) it would answer my major objection. I remain unconvinced as to the usefulness of such a feature though. Manuela Zuern : Of course only user defined names should be renameable. I believe this is a very useful feature, and important for proper software reuse which is one important aspect of object oriented programming. There are several examples for its usage : * Two operators defined in different modules developed by two different people have the same functionality but for different data types and therefore the operators names should be the same; an example for the two modules could be e.g. a sparse matrix module for matrices stored in jagged diagonal storage format and a sparse matrix module for matrices stored in row ordered list format. * Two operators defined in different modules developed by two different people have the same name but (slightly) different functionalities. The operators should therefore be distinguished by renaming at least one of them. 1.1.4 Regularize Handling of Pointer Arguments Richard Maine : Already being worked by X3J3 1.1.5 INTENT for pointers Richard Maine : Already being worked by X3J3 William Clodius : I believe that it would be usefull to specify the INTENT of pointers, but believe that it should specify not only whether the association of the pointer with a target can be modified, but also whether the target it is initially associated with can be modified. Not making the distinction I believe is error prone. Manuela Zuern : This requirement not only follows the natural Fortran way and turns off one common beginner mistake, but also is necessary for things like overloading pointer assignment (see my comment on 1.1.2) 1.1.6 Remove INTENT(IN) requirement for OPERATOR, ASSIGNMENT Christian Weber : This requirement must be satisfied if more complicated assignment routines - which perform garbage collection etc. - shall be implementable in Fortran. Malcolm Cohen : This proposed requirement is completely wrong-headed. Why someone would wish their operator function to write to a compiler-created temporary (which is probably then reused for something else or even deallocated) is beyond me, unless they WANT to write buggy programs. A thousand**thousand times no. William Clodius : I believe that this is influenced by some of the user coded optimizations that users of C++ have found to be usefull. Such optimizations include reusing the storage of one of the arguments for the result of the operator. I am in sympathy with the desire to have Fortran as efficient as possible, but I also believe that this, as stated, is error prone. It can allow an operator to have unintended side effects given Fortran's argument passing mechanism. I might suggest allowing operator arguments to have something along the lines of INTENT(TEMPORARY), which indicates that the operator may only be used on unnamed entities. Manuela Zuern : I do not really see the point why it has been implemented in the present Fortran Standard the way it is today. The INTENT attribute is a very useful attribute but should not be a duty to be specified in one special way in any context. In context with data abstraction it can be necessary to access some parts of an operator e.g. for some management reasons. One situation is if a function result is used as an operator in the same statement, it must be possible to destroy the function result at the end of the operation. Take the statement type(mytype) :: a,b,c,d d = a .myop. fu(b,c) In the case that 'mytype' is a complicated data structure with many array pointers pointing to arrays which have been newly allocated to be very large in function 'fu', such statements can result in memory leaks, because the arguments (operators) have to be INTENT(IN) and therefore must not be destroyed. 1.1.7 Intrinsic and User-defined Specific and Generic Names Dr. S. Morgan : #59 says nothing on estimated impact! Is there none??? Malcolm Cohen : This is already done in Fortran 95, so should be removed from our list. Manuela Zuern : As this is already done in Fortran 95, I voted to omit the item (if I knew that before I would not have put the item on the list anyway ...) 1.1.8 Operators for more than two arguments Christian Weber : I agree with Malcolm Cohen concerning this issue. Malcolm Cohen : Once again, this effectively means that any two programs which use such a feature are written in an entirely different language. Not to mention that it is a huge amount of work both for the standard and for implementations, just to avoid writing function references when one wishes to reference functions. Just say no. William Clodius : There are at least two different ways of providing this capability, which can differ from one another significantly in syntax and semantics, e.g., allow operators to have more than two arguments, or allow one of the two arguments to consist of multiple components, e.g., have Fortran's argument lists become a type along the lines of SML's tuples. If forced to choose, I would prefer the seond as a means of regularizing the language, but a. The additional capabilities this addition to the language would provide are small. b. I believe it would take a lot of discussion and effort to arrive at a concensus on the correct way to define this in the language. Patrice Lignelet: Should it be a reason among others, don't introduce "national" graphic characters, like [], if Fortran... Manuela Zuern : This requirement is not essential but very desirable. It gives the program developer the possibility to write his programs in a more natural way in the same expressions as he would formulate the algorithm on a piece of paper. Apart from the examples in the requirement in the repository I want to show further situations where this feature is useful. * Multilinear Operators c = a .(. x,y,z .). * Selfdefining and selfexplaining language elements .write. x .to_file. 'result_file.dat' The interfaces for operators for more than 2 arguments could look like the following ('#' is meant to be a symbol for a placeholder for an argument) interface operator (.<. #,# .>.) function dot_prod(aa,bb) result(alpha) type(vector) :: aa,bb type(scalar) :: alpha end function dot_prod end interface interface operator ( #=#.(.#,#,#.). ) subroutine multi_lin(cc,aa,xx,yy,zz) ... end subroutine multi_lin end interface interface operator (.write. # .to_file. #) subroutine print_to_file(xx,filename) ... end subroutine print_to_file end interface 1.1.9 Aliasing Type Definitions Michael Hennecke : This is very important, but I on not like the specs: in ``TYPE Float :: ALIAS = real(stnd)'' the type name declared is Float and apears IN FRONT OF the double colon. This is not what Fortran normally looks like. The Interoperability TR has a which I feel is more Fortran-like... Malcolm Cohen : Hey, having a double colon at all is not very FORTRAN-like... (we do not have to decide this anyway - if we put the requirement in, X3J3 will adjust the concrete syntax to make it fit in with the rest of the language). Patrice Lignelet: A variant syntax could be TYPE float => REAL(...) as "=>" symbol already has "renaming" semantics in Fortran (USE dcl.) Manuela Zuern: This one does not really belong to the Interface Generalization list, but I left it there not to confuse people more than I already did. 1.1.10 Allow s as actual arguments Christian Weber : I agree with Malcolm Cohen concerning this issue. Malcolm Cohen : This does not work, because multiple specific names are likely to be acceptable fits to the disambiguation algorithm (when you pass a generic name as an actual argument to a generic name...). Manuela Zuern : I do not fully see how this could work, but the idea should be kept in mind, because it is important for data abstraction to make specific names private and have access only via (generic) interfaces. 1.1.11 Consider an array as a single object; give POINTER attribute to array valued function results Malcolm Cohen : [allow immediate subscripting of array functions] This is effectively the user throwing away almost all of the return value of the function; all it shows is that they should have been calling a function that returns the answer that they want, instead of lots extra! [continued: give POINTER attribute to array-valued function results] This is completely unnecessary. If a user wants a pointer-valued array function, they can write it that way. There is no reason why for the sake of some small convenience to a vanishingly small proportion of users, we should make array functions leak memory (if they are POINTERs, we cannot just delete them without ensuring that it is impossible for another pointer to reference them...). Manuela Zuern : At this point there turns up another question not directly concerning this requirement. There is a possibility to simulate an array of pointers in Fortran 90. One might argue that this is simply the way how arrays of pointers are defined in Fortran, which is the following. integer,parameter :: nmax = 1000 type real_point real,pointer :: rp end type real_point type(real_point),dimension(nmax) :: rp_array The only way to allocate the pointers of this array is within a loop like do i=1,nmax allocate(rp_array%rp) enddo This of course results in bad performance due to the separate allocation of very small objects. A statement like allocate(rp_array(:)%rp) is not allowed, because in array syntax on the right hand side of the vector subscript no pointer may turn up. Due to vectorization this restriction is ok for most statements, but for the allocate statement the pointer targets do not exist or at least are freshly allocated, each single one without any dependencies. The performance could be improved for a number of codes if this kind of allocate statement was allowed. 1.1.12 Develop a template/functor feature for the language Jeanne T. Martin : Templates are very useful in C++, but they do not appear in the WG5 repository - so maybe should wait for F2005. Richard Maine : I think there might be something worthwhile here, but I don't think the proposal is developed and studied enough to be ready to add to the language in this revision cycle. Dr. S. Morgan: I think this would be a useful addition but it is not essential since the basic functionality is available with a good text editor even if this does cause unnecessarily large source files with more potential for error. Malcolm Cohen : This is not from the requirements database and there is no overwhelming demand for it. William Clodius : I believe that this is an extremely usefull capability for a language and I would be willing to develope a detailed proposal. Manuela Zuern : Concerning software engineering aspects in context with data abstraction I believe that this requirement is very useful and necessary to avoid the more than error prone copy-paste mechanisms for similar procedures. 1.2.1 Expression Clarification - Object Oriented Programming Stan Whitlock : I strongly urge the DATA subgroup to follow and enhance the direction started by John Cuthbertson in his paper X3J3/96-172 Dr. S. Morgan : This ought to be lumped in with considerations for OOF. (Also see my comments on Category 2) Malcolm Cohen : The "expression classification" part of this requirement does not appear to me to have anything to do with object-oriented programming, nor does it appear particularly desirable. Manuela Zuern: The "expression classification" part of this requirement is one of a couple of assumtions for a good working implementation of any new object oriented feature. 1.3.1 Derived Type I/O Jeanne T. Martin (H): This is being done by X3J3 and should not appear on the Data SG list. Dr. S. Morgan : Already (and rightly) a high priority in X3J3. Manuela Zuern : I would rather like to have a possibility to overload the 'print' and and 'read' statements than putting too much effort in some derived type I/O development. An overloaded print for a certain derived type has exactly the same functionality, less impact on the I/O structure, is very natural and Fortran like and easy to understand. Concerning the format specifier problem special print and read operators could be provided which can be specified by each 'class', rather than using the old 'print' and 'read' mixing up functionalities. Example could be something similar like below: interface print module procedure print_matrix end interface subroutine print_matrix(mat) !* contains only format specifications ! type(matrix) :: mat !* new format specification for special component printformat(FMT='...') mat% ... ... end subroutine print_matrix ... print44,' ** Components of matrix ',mat 1.4.1 Allow PUBLIC entities of PRIVATE type Jeanne T. Martin : Can be done by creating oft-used constants in the defining module. 1.4.2 Allow a PUBLIC operator USEd in a module to be made PRIVATE for further use. Jeanne T. Martin (O): already there Christian Weber : "O" only if Malcolm's solution works; otherwise I would vote for "L". Malcolm Cohen : This is not from the requirements database (it has nothing to do with requirement 74) and there is no overwhelming demand for it. The functionality is achievable in Fortran 90 anyway. To do this in Fortran 90, just do USE B,ONLY:BTYPE in the specification part of module A, and in each module procedure which needs .myop. do USE B Since .myop. cannot be used in the specification part of the module anyway, this causes no problem and does exactly what is wanted. 1.4.3 Separate specification of the access attributes of a derived type Malcolm Cohen : This is not from the requirements database and there is no overwhelming demand for it. Manuela Zuern : As Fortran is not going to be a pure object oriented language I believe that it is very important to have the possibility to specify visibility attributes for derived type components separately. I can see no reason why this has been implemented with the restriction anyway in Fortran 90 which is not an object oriented language, but object supporting. 3.1 Remove name class irregularities Jeanne T. Martin : I would personally like to see this taken care of, but it is a minor change and should not interfere with other more important additions. Dr. S. Morgan : The class of names issue caused difficulties in the parameterised derived types proposal but the solution has always met with strong opposition. It would be nice to have generic names in a unique class and the proposals in #15 seem sensible. 3.2 Regularize KIND parametrization intrinsics Richard Maine : different votes on the different parts of this really. selected_logical_kind - something likely needed for selecting logical kinds, but I'm not sure how best to express it. This isn't really very parallel to selected_[int/real]_kind, because it relates only to the storage used rather than to the set of representable values. So no vote on that part. radix specification - would really be nice to specify radix 2 for some cases so that one could specify numbers of bits. So medium priority on that. huge for character - the functionality would be useful, but I think that "huge" is the wrong spelling because it isn't parallel to the numeric huges, so vote to omit this (at least as expressed). Christian Weber : I agree with Malcolm Cohen concerning this issue. Dr. S. Morgan : I like the idea of regularity but don't see this as a high priority. Malcolm Cohen : 1. SELECTED_LOGICAL_KIND: We could just standardise the KIND numbers, or link them to the INTEGER kind numbers (i.e. LOGICAL(KIND=N) would be defined to take the same space as INTEGER(KIND=N)). 2. SELECTED_INT_KIND: The rationale argues that there is no way of selecting a 31-bit integer. This does not appear to be a problem - there are no machines around with 31-bit integers either. 3. It would be highly irregular for HUGE(X) not to have the same type and type parameters as X, so if it is extended to CHARACTER, it must return a CHARACTER result in that case. 3.3 Array Components of Array Structures Dr. S. Morgan : I can't remember why this was left out of F90 but I do seem to remember it was due to technical reasons. I haven't had time to look up X3J3/119-LJM-1. 3.4 Extend ALLOCATE to specify non-KIND type parameters William Clodius : The lack of this capability is a noticeable weakness of Fortran's character type, and with allocatable components and parameterized derived types it will be even more important to have such a general capability ============================================================================= ============================================================================= V. Comments on Requirements of Category-2 ========================================= V.1 General Comments on Category-2 items ========================================= Manuela Zuern: I believe the realization of some of the requirements which complete the existing data abstraction mechanisms already provided by the Fortran 95 standard are assumptions to implementing Object Oriented features like inheritance. But I find it also very important for Fortran's future to implement several Object Oriented features like inheritance, a 'CLASS' concept (however it is called), a better polymorphism and so on for the next revision of the Fortran standard. Object Orientation seems to be very important to me, not only because it is a more and more used technology but because software systems get larger and larger and therefore software engineering aspects like software reuse and extensibility gets more and more important. I don't see much future in Fortran if todays technologies will not be supported. Many people will switch to other programming languages, no matter of Fortrans advatages. People developing new software systems want to be flexible in changes and extensions (especially in research work) and also want to have high quality and high performance products. It is not very easy, especially via email, to find out what direction a future Standard should follow. What I wanted to gain through the subject votes was to get an overview on opinions what kind of object oriented features should and what shouldn't be included in Fortran 2000. I think we have got the overview now and can start to think about how these features should be implemented, based on the x3j3 paper 96-172 as I and many others would suggest. I would very much like to have further discussion on (only) the category-2 items before the Las Vegas meeting. If there is any, it will also be input for the subgroup work in Las Vegas. Several questions have not been included in the votes, but can be discussed from now on. I did not include a question on the importance of procedure variables (included in 2.2), because this subject is already be worked on by x3j3 as far as I know. I also know that I haven't included all possible questions on OO subjects in this vote but I took all suggestions in consideration which I got before I started the voting request and I believe those subject votes now give a basic idea on what should be implemented in the language. Dr. S. Morgan: I think the object oriented issues can't be discussed as separate issues. It seems to me that including inheritance in the language is useless if we don't have classes which link methods and types, and we don't allow overriding of methods. Dynamic polymorphism can't be considered separately from other issues. How big an impact would it have on implementations? I don't think I've seen much discussion of this. OO must be presented as one coherent package in a way that integrates with existing F90 and doesn't compromise efficiency of existing programs or new programs that don't use these features ... Therefore I'm voting to have OO discussed in Las Vegas but not voting on each separate issue - yet! (...) Jeanne T. Martin: As a proponent of OO in Fortran, I must caution the data group that it is vitally important for the slate of requirements we recommend to be minimal because: 1) The oponents of OO in Fortran must not be alarmed by a long and possibly inefficient-to-implement list. 2) X3J3 has limited resources and time to implement the requirements for F2000. 3) The simpler the presentation of requirements, the greater the likelihood of acceptance. We need to concentrate on what is REALLY important. FINAL COMMENT: We should come out strongly in favor of adding single inheritance and some form of dynamic binding (left up to X3J3?) and very little else in this category. Christian Weber : I am missing a question concerning the importance of procedure varables / pointers to procedures (which belong to subject 2.2). For these I would estimate *H*igh importance. Malcolm Cohen : We seem to be missing a few obvious questions here. I assume (!) we all agree the necessity of having polymorphic objects somehow, since they are rather necessary for OO, but beyond that there are: (i) tagged? - costs 4 bytes per object - provides runtime type enquiries, allows runtime type safety enforcement (ii) rooted object tree? - are REAL, INTEGER et al in the type classification tree? (iii) separate from derived types? (vs. extension of derived types) - cannot have rooted object tree - duplication of functionality (derived types and classes without methods) (iv) all objects are references? (requires separation from derived types) - even non-polymorphic usage pays polymorphic price (extra indirection) - reference semantics make assignment like pointer-assignment (v) non-polymorphic objects possible? - retain derived-type efficiency when possible - requires distinguishing poly from non-poly vars, either attribute (e.g. POINTER or ALLOCATABLE?) or keyword (e.g. TYPE vs. CLASS). ============================================================================= V.2 Comments on the votes of Category-2 ======================================== Vote 1: Should a constructor and destructor be implemented ? Jeanne T. Martin (L): This is really two questions. Constructors are used more frequently and reliably than destructors, but neither is essential. Christian Weber : The constructor for a derived type can be replaced by the inquiry of some preinitialized variable within the derived type; there is no replacement for the destructor feature, though, within the current Fortran95. Although "constructor & destructor" might seem low-level features at first glance, these would allow to build higher-level user modules upon these. Malcom Cohen : If fu1/2/3 are POINTER functions that might allocate things, it is a mistake to use them this way. Just have a non-POINTER version of the same function... This is very low-level, error-prone in use, and has a very limited domain of applicability. William Clodius : Many (most?) object oriented languages do not have an explicit concept of destructor, instead they rely on garbage collection. In C++, dealing with constructors and destructors in the presence of exceptions has proved difficult, as the correct semantics for dealing with partially constructed/destructed objects is not obvious. Manuela Zuern : Each allocation of a data object must have a corresponding deallocation of the data object. Sometimes this deallocation mechanism cannot be invoked by the programmer, e.g. in statements with function results including pointer components as arguments like a5 = fu1(a1, fu2(a2, fu3(a3,a4))) The function result of fu3 has to be destroyed in fu2 and the function result of fu2 has to be destroyed in fu1. But what is to do if the code of fu1 and/or fu2 is not accessible ? For further explanation see ISO/IECJTC1/SC22/WG5 N1187. This kind of object destruction has to be done by something like a destructor. A destructor is an operation that destroys an instance including maintaining referential integrity and deallocation its associated memory. A constructor is an operation that constructs (i.e., instantiates) an instance, allocates memory to dynamic objects, creates the bindings to operations, and initializes the values of the properties. ====================================================================== Vote 2: Should there be an extra clause like 'class' or something similar to distinguish derived types from classes ? Jeanne T. Martin (O): Let the implementation body determine this. John S. Cuthbertson : I do agree, in principle, with Malcolm Cohen on this issue: it doesn't matter if the actual construct is 'class', 'object', or 'type'. However not all programmers comment their code and so the code itself should be a documentary feature. Since there will be additional semantics associated with objects, the actual language syntax should reflect this. Christian Weber : I cannot see why derived types are not sufficient. Malcom Cohen : I do not agree. You have not shown why a derived type is insufficient. Whether it is called "CLASS", "TYPE", "FRED NURKE THE UNBELIEVER", or whether it simply follows from some aspect of the derived type definition is COMPLETELY UNIMPORTANT to the *requirements* phase. Surely the important requirement is to list what characteristics you want your "CLASS" thingy to have! All we have in this description is that it is some amorphous "abstract" thingy and that for some unspecified reason a derived type thingy from a derived type are not part of the requirements, they are done by X3J3 in translating our requirements into the new standard. PLEASE, .... LIST THE REQUIREMENTS! - like what extra does your abstract thingy have that a derived type both does not and can not have! William Clodius : There are several different ways of defining such an abstraction: A. Include the procedures syntactically in the derived type definition. This is similar to the class structure of C++. B. Syntactically mark the procedures as being associated with the "derived type". This is the method Oberon 2 uses. C. Indicate that the derived type implements a class, and implicitly associate all procedures associated with the derived type with that class. This is in essence what Ada 95 does. D. Create a separate construct to specify the attributes of an abstract class and its methods, and indicate which derived types implement the abstract class. This is in essence what Java and Modula 3 do. I prefer this method.) Manuela Zuern : In my opinion to keep the syntax of the language simple and clear it should clearly be distinguished between derived types (which might additionaly contain procedure pointers) in the Fortran 90 sense which can be used just as programmers are used to use them when programming Fortran 90, and classes in the object oriented sense, containing methods and being able to inherit data and methods. I don't mind if they are called 'Class' or whatever, but the clause should be different from 'derived type'. ====================================================================== Vote 3: Should Single Class Inheritance be implemented ? Christian Weber : It's obviously needed for OO. Malcolm Cohen : Yes, this is one of the cornerstones of OO. ====================================================================== Vote 4: Should Multiple Class Inheritance be implemented ? John S. Cuthbertson : Multiple inheritance is an 'additional' - we don't need it as part of the language for programmers to do some measure of OO programming. Single inheritance is sufficient. I would rather get single inheritance right and then bring in multiple inheritance in a later language revision. Christian Weber : It may be useful, but let's be modest to get started. Malcolm Cohen : No, this is one of the fripperies of OO. William Clodius : Most object oriented languages do not appear to implement multiple inheritence. Those that do appear to do so because of their strong association of dynamic dispatch with inheritence. This association is not required. I would rather get a strong single inheritence language defined ASAP, than devote a lot of effort towards multiple inheritence. Patrice Lignelet (O): Multiple Inheritance is quite a burden for the implementor (it has not been retained for Ada 95 for instance), and of practical misuse too often... Let's try Simple inheritance first, that will be enough and sufficiently valuable work as a start. Manuela Zuern (L): I find it important to also implement multiple inheritance in Fortran , but as far as I can see there are so many items which have high priority. Compared to those I would prefer having those now and multiple inheritance in a later standard. This assumes that single inheritance is implemented in a way that can easily be extended to multiple inheritance in a later revision. ====================================================================== Vote 5: Do we need additional visibility attribute(s) outside class relations ? Malcolm Cohen : Yes, we all know what "information hiding" is, but you do not say exactly what it is you want your additional visibility attributes to do. Presumably not "information hiding" since PRIVATE does that with 100% efficiency already. Manuela Zuern : This additional visibility attribute outside class relations is meant to give (restricted?) access to specified (friend?) 'classes' but no access to the others. ====================================================================== Vote 6: Do we need additional visibility attribute(s) for related classes ? Jeanne T. Martin (L): The need for this depends on how inheritance is implemented. It should not be a high level requirement. John S. Cuthbertson : The present PRIVATE/PUBLIC visibility of derived types is probably sufficient for the level of support for OOP that we're aiming for. It is probably desireable to have more than two levels of visibility, but its going to cost and we not have enough time to do it. Christian Weber : All this may be desirable, but it is not essential to get started with a first step towards OO. Malcolm Cohen : These votes were based on my best guess as to what might be intended. In the end, however, I cannot support anything this vague. Patrice Lignelet : I think that Eiffel policy, for instance, is right: a Class inherits all "family secrets", and clients see only exported features. Manuela Zuern : At least if classes are related there should exist an additional visibility attribute to allow children classes the access to parent attributes or methods which are not visible outside the class tree. ====================================================================== Vote 7: Do we need dynamic binding for Fortran ? John S. Cuthbertson : This is the one issue that will be the most controversial, but a lot of the so-called benefits of OO methods are achieved through this feature. Malcolm Cohen : For this to make sense we need polymorphic objects. Then there are two obvious dynamic binding possibilities: (1) use our existing generic rules with the new polymorphic objects (perhaps with some extra rules added) to allow procedure calls to be disambiguated according to the runtime type of the objects. (2) add a completely new, orthogonal facility for message passing, where the procedure to be picked is determined by a single polymorphic object. Possibility (1) is the most natural way of extending what we currently have, though it could be tough to make it efficient. Possibility (2) could be provided by using the procedure pointer facility, relieving us of the necessity of doing it ourselves. I agree that dynamic binding of procedure calls is important (though not quite as important as polymorphic objects), but we need to spend more time working out what it is we want. In the end, I would be satisfied with possibility (2) if we cannot get possibility (1) to work. William Clodius : But it should be clearly distinguised from static binding Patrice Lignelet : Yes, if we consider "cones of classes" (as in Ada 95 for instance), where the "true" class of an object is unknown at compile time. ====================================================================== Vote 8: If inheritance is implemented, should subroutines be overridable ? Jeanne T. Martin (N): What does this mean? Any extended type/class can override an operation/assignment/method from the parent class. John S. Cuthbertson : Changing the behaviour of an inherited procedure is very important and taken for granted in OO modeling. Christian Weber : (I don't fully understand the question). Malcolm Cohen : Like Bill Clodius, I find this question difficult to understand. It seems to be a complete non-sequitur. What has "inheritance" got to do with "subroutines"? William Clodius : It is not clear to me what is meant by this. Do you mean inheritence of parametric polymorphic types, by parametric polymorphic types, inheritance in general? Overriding of inherited procedures is common for normal "classes", although it requires care in deciding how to specify which can be overridden, and how to syntactically indicate which should be referred to in a given context, i.e., the new or the overriden procedure. Overriding of the procedures of parametric polymorphic types strikes me as error prone. I would prefer to punt on this until we have experience with other aspects of the model. Let's not develope multiple aspect of the model simultaneously. Instead get the minimum defined clearly by the year 2000 and worry about the bells and whistles later. Manuela Zuern : As it is not necessarily clear that methods which are inherited from a parent class can be overridden by a child class, the ability to do so is something like an 'extra feature' which has been asked in the votes separately. If it is possible to override methods, the methods name is generic. If not, the methods name might turn up in a gerneric interface specification. I believe that it is very important if any kind of class inheritance should make a sense to have the ability to override methods. ============================================================================= =============================================================================