Re: A question about OOP in Fortran?
- From: "James Giles" <jamesgiles@xxxxxxxxxxxxxxxx>
- Date: Wed, 18 Jul 2007 23:49:32 GMT
So let's review.
glen herrmannsfeldt wrote:
....
I was only trying to claim that a class could have an
ordering method, not that they all do. If you create a
class that does have an ordering, it is suggested to include
a compare method.
My confusion was based on the fact that I've never seen this
approach recommended. Most promoters of inheritance
(books, articles, etc.) describe polymorphism as being based
on the class hierarchy, not being based on bypassing it. What's
the point of having a complex, difficult to learn, hard to read
paradigm if you're going to just ignore it anyway?
So, it's usually recommend that a class be created (call it
"ordered") to which the compare methods are all type bound.
And the sort is also bound to the "ordered" class. Now the
compiler can determine (at compile time) whether the call
to the sort is being applied to an appropriately ordered type.
No waiting till run-time to discover that you tried to sort an
array of complex numbers!
Well, that's the first problem with the usual hierarchical
technique - the intrinsic types are often not part of the
class hierarchy and so the polymorphic procedures can't
be applied to them. I don't remember whether Java does
this or not (nor do I care - though I guess I can't prevent
someone for telling me). Another problem is that the
property of being ordered is not something that fits into
a hierarchical arrangement of types very well.
What Glen has described is a way to coerce the hierarchical
type system into clumsily supporting non-hierarchical
polymorphism. He binds his sort routine to the root class
and then it can be applied to anything (well, anything whose
type is in the hierarchy). It then only works when the argument
actually *has* an ordering relation (ie. has comparisons defined
on it). But, by his own statement, this isn't discovered until
run-time. Well, given the choice I think I'd prefer to have a
directly implemented non-hierarchical polymorphism feature.
(I've got to find a clever acronym so I don't have to write
such a long phrase each time.) It would not only be simpler
and more legible, but I'm convinced implementations would
run faster.
.........
For heterogenous collections Glen has used the same trick of
using the coercing the type system into bypassing the hierarchy
entirely. Some of the same observations above apply here.
The result is certainly less legible and I'm convined it's bound
to be slower in most cases.
Notice I said "collections" above. Hashtables are just one
kind of collection. The specific properties of hashtables are
mostly irrelevant to the general issue of heterogenous collections.
It's best to keep the discussion to a simpler sort of collection and
not confuse the issue with specifics of hashing. I recommend an
array, though a linked list is a good example too.
So let's say I want an array with heterogenous elements.
To pick a deliberately hard case, suppose I want the list to
contain only COMPLEX or RATIONAL. This is hard because
COMPLEX is an intrinsic type and RATIONAL isn't, and also
because they both take up two numeric storage units.
What I prefer to do is just declare a variant derived type, or a
union, or whatever you want to call it. And then I want to
declare an array with that variant type as the base type of
the array:
Type my_variant
.... Something that describes a union of COMPLEX and
.... RATIONAL as the only variants of the type.
End type my_variant
...
Type(my_variant) :: array(50)
...
array(1) = 3 .over. 5
array(2) = (3.0, 5.0)
array(3) = "abc" ! this is flagged as error at compile time
More of this example later. But there's already quite a
lot that needs work to fit it into Glen's scheme. First is that
he would declare an array whose base type is CLASS(*),
except that I'm not sure that COMPLEX is considered part of
CLASS(*). I've read the F2003 standard through a few times
looking specifically for whether CLASS(*) can apply to
intrinsic types, and I still don't know. Second is that Fortran
and apparently, from what Glen says, Java) requires poly-
morphic elements of a collection to be pointers (references)
or allocatable (Fortran only). Hence:
Type Glen_variant
Class(*), allocatable :: data
End type Glen_variant
...
Type(Glen_variant) :: array(50)
...
array(1).data = 3 .over. 5
array(2).data = (3.0, 5.0)
array(3).data = "abc" ! won't be flagged as error by compiler
I *think* it may work this way. I don't have an F2003 compiler
to play with, so I can't be sure. If this isn't right, then there's
probably a necessity to code defined assignment operators
or something. We already have an unnecessary extra level
of indirection and memory allocation going on. That additional
work would just make things even less convenient. (On the
other hand, if defined assignments *are* required, then maybe
that last assignment *would* be caught at compile time since
you wouldn't have defined an operator for that combination
of types.)
It's slower because of the indirection, it's not as safe, and
there's no clear mention that the array should only hold COMPLEX
or RATIONAL values - there's no mention of that at all, in fact.
There's no way to mention it except in comments.
Continuing the Glen_variant example, here's a loop that processes
the array after it's fully defined:
Do i = 1, 50
Select type (array(i).data)
Type is (complex)
... handle complex Array(i).data here
Type is (rational)
... handle rational Array(i).data here
End select
End do
Fortran 2003 doesn't have a type inquiry function, it only has this
clumsy new control construct. Notice that the third array element
(the one I assigned a string to) is simply skipped here. The error
is never caught. Sure, there is a CLASS DEFAULT clause you could
add to the SELECT block that could catch such a thing. This is what
I call "boy scout" programming. Students promise to use such
defensive programming (even with left hand on Principles Of
OPeration and right hand raised holding a language reference
card) but cease to ever do so after the instructor is out of sight.
So the above has three failings with respect to the error handling:
it's not at compile time, it's optional, and even if present it's remote
from the site of the error.
Getting back to my original example, let's suppose that the union,
variant type, whatever is tagged and that the way to determine
which tag is to use the tag name as an inquiry function name:
Do i = 1, 50
If (a_complex(array(i)) then
... handle complex Array(i) here
Else
... handle rational Array(i) here
End if
End do
Notice it doesn't even test for the rational case. It's not necessary.
It couldn't be anything other than a complex or a rational anyway.
The assignment is typesafe (though I am presuming that the
values default on declaration to one of the valid variants).
Now probably I didn't do the Fortran examples right, F2003
doesn't exist as a complete implementation yet (at least I don't
have one). And it's not always obvious without testing and
then discussing the results to know what the standard actually
says. Most of us don't have the advantage of several years
of debate in committee.
And in spite of all I've said, it's true that in the absence of
real generic programming, this idea of coercing the class
hierarchy into simulating such is a little interesting. It's
certainly an improvement on messing with inheritance.
Similarly, if I don't have variant derived types, the similar
idea of making arrays or "anythings" is maybe a barely
acceptable stop-gap (assuming obvious things like using
transfer and other type cheats are not available).
--
J. Giles
"I conclude that there are two ways of constructing a software
design: One way is to make it so simple that there are obviously
no deficiencies and the other way is to make it so complicated
that there are no obvious deficiencies." -- C. A. R. Hoare
.
- Follow-Ups:
- Re: A question about OOP in Fortran?
- From: Paul Colin Gloster
- Re: A question about OOP in Fortran?
- References:
- Re: A question about OOP in Fortran?
- From: Arjen Markus
- Re: A question about OOP in Fortran?
- From: Colin Paul Gloster
- Re: A question about OOP in Fortran?
- From: glen herrmannsfeldt
- Re: A question about OOP in Fortran?
- From: Colin Paul Gloster
- Re: A question about OOP in Fortran?
- From: glen herrmannsfeldt
- Re: A question about OOP in Fortran?
- From: James Giles
- Re: A question about OOP in Fortran?
- From: glen herrmannsfeldt
- Re: A question about OOP in Fortran?
- From: James Giles
- Re: A question about OOP in Fortran?
- From: glen herrmannsfeldt
- Re: A question about OOP in Fortran?
- From: James Giles
- Re: A question about OOP in Fortran?
- From: glen herrmannsfeldt
- Re: A question about OOP in Fortran?
- From: James Giles
- Re: A question about OOP in Fortran?
- From: glen herrmannsfeldt
- Re: A question about OOP in Fortran?
- Prev by Date: Re: random_seed
- Next by Date: Re: A basic question about linked list
- Previous by thread: Re: A question about OOP in Fortran?
- Next by thread: Re: A question about OOP in Fortran?
- Index(es):
Relevant Pages
|