From vsnyder@math.Jpl.Nasa.Gov  Fri Jan 24 21:01:06 1997
Received: from eis-net-001.jpl.nasa.gov (eis-net-001.jpl.nasa.gov [137.78.57.19]) by dkuug.dk (8.6.12/8.6.12) with ESMTP id VAA19681 for <sc22wg5@dkuug.dk>; Fri, 24 Jan 1997 21:01:01 +0100
Received: from math.Jpl.Nasa.Gov (math.jpl.nasa.gov [137.78.227.106]) by eis-net-001.jpl.nasa.gov (8.7.5/8.7.3) with ESMTP id MAA16033 for <sc22wg5@dkuug.dk>; Fri, 24 Jan 1997 12:00:58 -0800 (PST)
Message-Id: <199701242000.MAA16033@eis-net-001.jpl.nasa.gov>
Received: by math.Jpl.Nasa.Gov
	(1.37.109.15/16.2) id AA061125979; Fri, 24 Jan 1997 11:59:39 -0800
From: Van Snyder <vsnyder@math.Jpl.Nasa.Gov>
Subject: Comments on N1238
To: sc22wg5@dkuug.dk
Date: Fri, 24 Jan 1997 11:59:39 PST
Reply-To: <vsnyder@math.Jpl.Nasa.Gov>
X-Mailer: Elm [revision: 109.14]

I've studied N1238, but not the documents referenced therein.

As was said about US President Calvin Coolidge's inauguration speech, it
appears to be "An army of phrases marching in search of an idea."

As I advocated in 1986, Fortran designers should strive to extend and
generalize existing mechanisms before inventing new ones.

One should also keep in mind that programs are read many more times than
they're written, so developing structures that allow the program author
to express intent most clearly are advantageous.

With that preamble, here are my specific comments.
-----------------------------------------------------------------------
Section 1.1.8 Operators with more than two arguments:
In addition to allowing program authors to define operators with more
than two arguments, an intrinsic distfix if-then-else operator, with the
same semantics as the C ...?...:... operator would simplify some logic. 
On the other hand, Malcolm Cohen frequently argues that "there's little
demand for it."

To avoid C-like crypticisms, don't use ?:.  Maybe use an intrinsic
IF(Predicate,ThenExpr,ElseExpr), in which
 1.  Predicate must be of type LOGICAL
 2.  ThenExpr and ElseExpr must both be numeric, or else both of
     the same type
 3.  The result type is converted as it would be for mixed-mode
     arithmetic if ThenExpr and ElseExpr are numeric, else is their type.
-----------------------------------------------------------------------
Section 1.1.9 Aliasing type definitions:
This issue should be considered in the context of construction of a
complete and systematic type and subtype system.

Aliasing type definitions, as described here ("simply a synonymn for some
other type name") is less than frivolous.  It makes program maintenance
more expensive and error prone.  It _is_ useful to be able to declare a
new type that has identical semantics and code generation methods to
an intrinsic type, but it should thereafter be considered to be a
separate derived type.  It would be OK to inherit existing intrinsic
operations for the base type, but combining and assigning should be
prohibited, except by explicitly overloaded operators.

If one wants to define a new name for a collection of values, but allow
inter-convertibility to another collection of values, and allow using the
same set of operations, one should use a _subtype_.

All of this has been thought through several times before.  I can't urge
too strongly that prior work, especially Ada 83 and Ada 95, be studied
before proceeding.  One must avoid the "ready, fire, aim" approach.

A complete consistent system of types and subtypes is needed.  Best
would be to construct one.  Piecemeal implementation preserves the
"beloved Fortran tacked-on look" but risks getting the language
"painted into a corner."

See my comments at http://gyre.jpl.nasa.gov/~vsnyder/fortran/type.html
and in X3J3 97-114.
-----------------------------------------------------------------------
Section 2.1.2 Constructors and destructors:
Its a very bad idea to associate constructors with ALLOCATE and
destructors with DEALLOCATE.  They belong to the _type_ of object being
allocated and deallocated.

Constructors should be _invoked_ when objects are created, no matter
whether by coming into scope, or by an explicit ALLOCATE statement, and
destructors should be _invoked_ when objects are destroyed, no matter
whether by going out of scope, or by an explicit DEALLOCATE statement.

Don't confuse the static relation between a collection of values and
related operations thereon with the orthogonal issue of scheduling of
operations.

It would also be worthwhile to look at the Ada 95 "controlled" class.
Classes that inherit from "controlled" can have "initialize", "update"
and "finalize" procedures.  On the other hand, the need for three
procedures instead of two arises from Ada not allowing to overload the
assignment operator.
-----------------------------------------------------------------------
Section 2.2.1 Procedure variables, items (4) and (5):
A declaration of a procedure-valued variable _must_ include the type
signature of the arguments (and return type for functions).  It should
only be allowed to assign a procedure to a procedure-valued variable if
the interface to the procedure is explicit, and the "type signature" of
the procedure matches the variable.  There are also issues of lifetime.

See my comments at http://gyre.jpl.nasa.gov/~vsnyder/fortran/procedures.html
and in X3J3 97-114.
-----------------------------------------------------------------------
Section 2.2.1 Procedure variables, item (7):
If a derived type "contains" a procedure, then something like "name
mangling" (forgive the C++ jargon), or a Fortran-specific linker, is
needed.  The trajectory of Fortran is to require external names to be
unique.

Ada 95 has an excellent object-oriented programming system, and manages
to associate procedures to classes simply by using the ordinary rules for
polymorphism, plus some simple extensions so that procedures that
"belong" to a base class can be used with objects of a derived class.

In 1986, I and Rex Page (and perhaps others) advocated a notation F(R) to
access a "field" F of a "record" R, instead of R%F.  With F(R), if F is a
procedure, it's quite obvious that the existing generic mechanism works.

But one can make R%F work simply by stipulating that if F is a procedure
that takes an argument of the type of R, invoke it with R as its
argument.  This is not a new idea -- it was in Mesa before 1975.

See my comments at http://gyre.jpl.nasa.gov/~vsnyder/fortran/uniform.html
and .../field.html (linked from ...uniform.html), and in X3J3 97-114.
-----------------------------------------------------------------------
Section 2.3:
Programming language theorists almost unanimously agree that multiple
inheritance is never _necessary_ -- one can always use inclusion instead.
Furthermore, it creates numerous problems -- the most famous example is
the "dreaded diamond-shaped inheritance diagram."  I agree with the
consensus in vote 4 in section V.2, especially William Clodius's remarks.

I'm pleased to see that there are proposals based on Ada 95, but I
haven't read them yet.  C++ was poorly and hurriedly done.
-----------------------------------------------------------------------
Section 2.4.1 Additional visibility attribute:
In 1986, I advocated separate specification and implementation modules. 
It solves this problem, and has additional benefits outlined in my
comments at http://gyre.jpl.nasa.gov/~vsnyder/fortran/modules.html.

By building inheritance on "child units" as in Ada 95, additional
accessibility attributes aren't needed.

Don't multiply mechanisms when extending another will solve several
problems all at once (including this one).
-----------------------------------------------------------------------
Section 2.5.1 Class inheritance and dynamic binding polymorphism:
I'm pleased to see that there is a proposal based on Ada 95, which I
consider to be superior to the C++ mechanism.  I haven't read N1188 or
N1189 yet.  For those who aren't aware of the difference:

C++ uses a "virtual" declaration for classes and procedures to indicate
run-time dispatching (dynamic binding polymorphism).  Ada uses a
"class-wide pointer."  If one fails to make a C++ destructor virtual,
numerous hard-to-find problems arise.  Furthermore, Ada's class-wide
pointer is type-safe.  This is one of the reasons that Les Hatton
(les_hatton@prqa.co.uk) has observed that C++ programs have about three
times the maintenance cost of programs written in C, Fortran or Ada.
-----------------------------------------------------------------------
Section 3.2 Regularize KIND parameterization intrinsics:
If SELECTED_INT_KIND is overloaded to take two integer arguments, viz.
lower bound and upper bound, instead of number of digits and radix, one
gets at least two other benefits in addition to the one desired here:
 1.  Unsigned integers.
 2.  "Free" bounds checking for subscripts.

Malcolm Cohen's remark "There are no machines around with 32 bit integers
either" misses the mark.  I and my colleagues at JPL have written large
volumes of Fortran software to process spacecraft telemetry.  The lack of
precisely specifiable integer types caused significant portability
problems.  Some of these programs, written for Voyager using
vendor-specific features of the Fortran (66) compiler, are trapped on
Univac-1100 computers, and may need to stay there for another 30-40
years!  (Unless somebody comes up with a few $millions to convert the
programs -- most likely to C.)

Don't multiply mechanisms when extending another will solve several
problems all at once (including this one).

See my comments at http://gyre.jpl.nasa.gov/~vsnyder/fortran/type.html
and ...subtype.html, and in X3J3 97-114.
-----------------------------------------------------------------------
Part III, data-E3 Develop a template / functor feature for the language:
This is a good idea, but the proposal
  INTERFACE OPERATOR (">")
    LOGICAL FUNCTION Wibble (x,y)
      TYPE(A,B,C,D), INTENT(IN) :: x, y
  ...
is one of the reasons "generics" didn't get into Fortran 90.  It causes
a combinatorial explosion -- 2**4 procedures in this case.  If you have
ten arguments and six types, you have 10**6 procedures!

Don't let the user make this kind of mistake lightly.
-----------------------------------------------------------------------
Part III, data-E4 Separate specification of the access attributes of a
derived type:
This is an idea that I proposed during public comment on Fortran 90.
I still like it.

There is a remark "In strict object oriented programming one would always
access derived type components via an interface."  I presume by
"interface" the author means "procedure".

Schools have been taught this discipline since David Parnas wrote "On
the criteria for decomposing programs into modules" which appeared in
Communications of the ACM in December 1992.  Parnas was concerned about
the fragility of programs when they're changed.  His goal was to allow
one to change the representation of objects without changing the
usages.  His context was "how can this be done using currently existent
languages."

Geschke and Mitchell, and Ross, and perhaps others had a superior idea,
described in "On the problem of uniform reference to data structures"
which appeared in IEEE Transactions on Software Engineering in June
1975, and in "Uniform referents: An essential property for a software
engineering language" which appeared in Software Engineering, Volume 1
in 1969 (Edited by J. T. Tou), respectively. The desire is to _design_
_the_language_ to reduce the "fragility" of programs, without
introducing the performance and memory penalties of procedural
encapsulation, the intellectual penalty on the author, or the next poor
schmo, who must write (read) numerous trivial procedures, and keep in
mind what each one does.

The idea is that reference to an "object" should have the same syntax, no
matter whether the object is a record field or a procedure or an array
element.

See my comments at http://gyre.jpl.nasa.gov/~vsnyder/fortran/uniform.html
and in X3J3 97-114.
-----------------------------------------------------------------------
Section V.2, Vote 2 Should there be an extra clause like 'class' or
something similar to distinguish derived types from classes?
Ada 95 gets along fine with a "tagged" attribute for types from which
others can be derived (by extension).  There's no separate "extendable"
or "extension" statement of comparable stature to "type."  An extra
clause is better than an extra construct.

See remarks above, at http://gyre.jpl.nasa.gov/~vsnyder/fortran/uniform.html,
and in X3J3 97-114, about a complete and consistent type system.
-----------------------------------------------------------------------
Section V.2, Vote 5 Do we need additional visibility attribute(s)
Manuela Zuern remarked "This additional visibility attribute outside
class relations is meant to give (restricted?) access to specified
(friend?) 'classes' but no access to others."

If object-oriented programing is based on modules, as it is done in Ada
95, instead of types, as in C++, and modules have separate specification
and implementation parts, and "child units," there's no need for the
complication of "friends" and "protected" visibility.

Don't multiply mechanisms when extending another will solve several
problems all at once (including this one).

See my comments at http://gyre.jpl.nasa.gov/~vsnyder/fortran/modules.html
and ...oof.html, and in X3J3 97-114.
-----------------------------------------------------------------------
Section V.2 Vote 7 Do we need dynamic binding for Fortran:
Patrice Lignelet remarked "Yes, if we consider 'cones of classes' (as in
Ada 95 for instance), where the 'true' class of an object is known at
compile time."  This is a very important observation.  More importantly,
the "class-wide pointer" instead of the "virtual" class or function,
allows compile-time type checking of procedure usage.
========================================================================

I shall tax your patience again after I read N1239, N1240, N1187, N1188
and N1189.

Best regards to all,
Van Snyder
