[J3] [EXTERNAL] Elemental type-bound functions not useful
Brad Richardson
everythingfunctional at protonmail.com
Tue Mar 30 15:51:11 UTC 2021
Van's whole question revolved around wanting `bar` to be elemental. But, as you have hinted at in your answer, the best you can do for the declared type of `x%bar()` in that case is `class(foo), allocatable, dimension(size(x))`. Even if you change that to `classof(x)`, it still resolves to the former at compile time, because that is as much as can be known at compile time. But, the return from an elemental function can't be allocatable, and that's the problem.
This is exactly the goal of the generic programming effort. With templates, you defer the instantiation and generation of code until the use site, so you have all the concrete type information around to be able to write something like this without runtime polymorphism.
Regards,
Brad
On Tue, 2021-03-30 at 15:40 +0000, Bill Long wrote:
>> On Mar 30, 2021, at 9:59 AM, Brad Richardson via J3 <j3 at mailman.j3-fortran.org> wrote:
>>
>> The declared type of an entity can't depend on the dynamic type. It's fundamentally backwards. The declared type must be known at compile time, but the dynamic type is only known at run time. At best you know possible dynamic types at compile time, but even then the set is not fixed and bounded. Someone can later create a new type that is extended from your declared type, compile it separately and your code is supposed to still work with it.
>>
>> As an example, say I have a subroutine `A` that takes in a `class(foo)` array argument.
>>
>> ```
>> subroutine A(x)
>> class(foo), intent(in) :: x(:)
>> ...
>> y = x%bar()
>> end subroutine
>> ```
>>
>> What must the declared type of `y` be if `bar` returns `classof(x)`?
>
> Well, the variable y should have a declaration - I’m guessing the default REAL is not sufficient here. Probably:
>
> class( * ),allocatable :: y
>
> in which case Y has no declared type. After the assignment, the dynamic type of Y would be the dynamic type of X.
>
>> You can't know until run time, so you can't compile it.
>
> A lot of OOP stuff is deferred until runtime. There is a lot of runtime overhead associated with OOP. Which is part of the attraction of templates, which are resolved at compile time. You might end up with many instances of a particular template, depending on how it is called. But all that mess is invisible to the programmer.
>
> Cheers,
> Bill
>
>> Regards,
>> Brad
>>
>> On Tue, 2021-03-30 at 14:41 +0000, Bill Long via J3 wrote:
>>
>>> In (partial) defense of Van, we did encounter a C++ code that had nested classes more that 75 layers deep, breaking the debugging tool the customer was using. While restricting nesting to just 1 level might be too extreme, programmers should show some sense of restraint. And gratuitous abstraction can make code unreadable and unmaintainable, especially when the error is in a layer of nesting above the ones you wrote.
>>>
>>> Cheers,
>>> Bill
>>>
>>>> On Mar 30, 2021, at 7:59 AM, Clune, Thomas L. (GSFC-6101) via J3 <j3 at mailman.j3-fortran.org> wrote:
>>>>
>>>> The depth of a chain of type extensions really should depend on the specifics of the use case. Certainly there is always some value to having a purely abstract base class, as it enables loose coupling with client code. And limiting the chain is only wise given the observed fragility in most compilers even at this far remove from 2003
>>>>
>>>> But there are common situations that require a few more degrees of inheritance are quite appropriate. As a specific example, the Java unit testing framework JUnit has an internal chain of classes:
>>>> • SelfDescribing (pure abstract)
>>>> • TypeSafeSelfDescribing (concrete instantiation for handling incompatible arguments to the primary method)
>>>> • Matchable (still abstract, but adds virtual method for comparing an object with anything else -- class(*)
>>>>
>>>> Users then extend Matchable in their own unit tests to wrap their own types. This allows the user to exploit the powerful grammar for composing diagnostic messages for failing tests. This is a perfectly reasonable (and highly successful!) OO design. And I don’t think it is the deepest such chain in the framework.
>>>>
>>>> Alas, the Fortran analog of the above breaks gFortran when I have an almost trivial extension of Matchable and then an extension of the extension. (Needed to test the ability to store objects of any dynamic types within one of my container classes.) And this is without even trying to emulate the ultimate base class “Object” that is underlying Java. So a major driver for OO design shifts form maximizing power/expressiveness to keeping it simple so as to remain portable across multiple compilers. Sigh.
>>>>
>>>> From: J3 <j3-bounces at mailman.j3-fortran.org> on behalf of j3 <j3 at mailman.j3-fortran.org>
>>>> Reply-To: j3 <j3 at mailman.j3-fortran.org>
>>>> Date: Monday, March 29, 2021 at 9:34 PM
>>>> To: j3 <j3 at mailman.j3-fortran.org>
>>>> Cc: Damian Rouson <damian at sourceryinstitute.org>, j3 <j3 at j3-fortran.org>
>>>> Subject: Re: [J3] [EXTERNAL] Elemental type-bound functions not useful
>>>>
>>>> On Mon, Mar 29, 2021 at 6:11 PM Van Snyder via J3 <j3 at mailman.j3-fortran.org> wrote:
>>>>
>>>>> Fortran doesn't yet have "sealed" or "inextensible" types (unless I missed something that prevents creating an extension type).
>>>>
>>>> One can prevent type extension by declaring a type-bound generic procedure with the same name as the name of the type as one might do to effectively write a type-bound, user-defined structure constructor:
>>>>
>>>> type foo
>>>> contains
>>>> procedure :: foo_constructor
>>>> generic :: foo => foo_constructor
>>>> end type
>>>>
>>>> My thoughts are aligned with those of Tom and Vipul. Once Fortran supports generic programming, I suspect it will displace type extension for most of my purposes. For now, I strive to limit type extension to extending abstract types. We sometimes have a non-abstract type extending an abstract type that extends another abstract type, but that's as deep as our hierarchies go in practice. We frequently combine type extension with type-bound operators, but I'm not crazy about the type-guarding that this approach requires. It feels like the developer is being burdened with ensuring runtime type safety as a stand-in for compile-time type safety, which is why I suspect I'll replace type extension with generic programming.
>>>>
>>>> Damian
>>>
>>> Bill Long longb at hpe.com
>>> Engineer/Master , Fortran Technical Support & voice: 651-605-9024
>>> Bioinformatics Software Development fax: 651-605-9143
>>> Hewlett Packard Enterprise/ 2131 Lindau Lane/ Suite 1000/ Bloomington, MN 55425
>
> Bill Long longb at hpe.com
> Engineer/Master , Fortran Technical Support & voice: 651-605-9024
> Bioinformatics Software Development fax: 651-605-9143
> Hewlett Packard Enterprise/ 2131 Lindau Lane/ Suite 1000/ Bloomington, MN 55425
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.j3-fortran.org/pipermail/j3/attachments/20210330/3e383e67/attachment-0001.htm>
More information about the J3
mailing list