-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
More flexible SELECT TYPE #38
Comments
In the above codes, a, b, and c are supposed to be some dummy arguments of class(*)? (and so the purpose of the code is to determine their dynamic types in a subroutine, for example?) If that is the case, I'm wondering if the same thing may be achieved by generics with constraints (like "where" in some languages?) |
Yes, something like this: integer function multiply_by_two(a) result(d)
class(*),intent(in) :: a
select type (a)
class is (integer(kind=*)) ! new syntax
d = a * 2
end select
end function multiply_by_two Or, via some sort of a limited polymorphic dummy argument like so: integer function multiply_by_two(a) result(d)
class(integer(kind=*)),intent(in) :: a ! some new syntax like this -- any integer kind
d = a * 2
end function multiply_by_two Maybe a sort of "poor man's" generics. |
I think this is a great idea. I went through the process a few years ago of creating a library of Abstract Data Types (lists, queues, RBtrees, hashmaps etc) using unlimited polymorphic containers etc. I went the extra mile and decided to support all the intrinsic types plus a user defined type. This started as a project to learn something about UP and kind of got out of hand. I can safely say that it doesn't take long before you really really hate SELECT TYPE and baseing ADTs on unlimited polymorphic values is NOT the best approach. We really do need templates or something similar for that. I even went so far as to emulate what Jacob is suggesting by creating my own enumerator parameters for each intrinsic type and my user type along with a function that takes an unlimited polymorphic value as an argument and returns one of my enumerator parameters as an INTEGER. I then use this value as a CASE selector in SELECT CASE just so I can do SELECT CASE(kind_type)
etc. |
I have made analogous comments to the committee in a slightly different context (SELECT RANK). There was a strong objection to having multiple cases in one statement. E.g. RANK(1,3,5). The reason given was that the compiler is generating rank-specific code within the clause. Putting multiple type/kinds within the TYPE IS clause would be even worse, so I am doubtful that aspect could proceed. As a developer, I find these arguments a bit frustrating. It is of course quite obvious how to write a preprocessor that would repeat the clause for each item in the list. But apparently this is much more difficult/subtle inside the compiler. However, those objections would not affect the desire to put multiple variables in the SELECT TYPE statement. There is a common pattern of nested SELECT TYPE's that have been complained about during meetings on multiple occasions. I can't recall what sort of syntax was proposed if any, but I like what I see here. |
The frequent need for nested "select type" statements is indeed an abomination in present Fortran. However, I am in favor of getting completely rid of such "downcasting" as it is called in other languages and to not ever have to use it at all. Select type statements are just a nasty symptom, and not the actual disease. The disease is that Fortran presently does not support any form of multiple inheritance. If we had Java-like interface inheritance (or traits as they have been called in Issue #125) in addition to implementation inheritance (the one that present Fortran provides), there would be no need to use "select type". The same would hold if we had C++ like multiple inheritance. It is the conflict between having to conform to some extended type's interface while at the same time wishing to inherit implementation from a base type that typically leads to the use of "select type" statements. |
I also suggested this in a Fortran Discourse thread Allow TYPE IS to select multiple types, where there was both support and opposition. A few people said they often had identical code for several |
The compiler developers were adamant that "the way compilers work" does not allow such seemingly simple code transformations as to replicate code for multiple cases in this manner. (For both SELECT RANK and SELECT TYPE. I don't recall the TYPE IS case being discussed, but possibly the same reason exists. But it would seem to be even simpler as there is no dependent code to compile and execute in this case. I will say that the "frequent need" for SELECT TYPE does diminish considerably in many cases with careful design. The primary ones that do not involve intrinsic types. E.g., a common case that two objects must have the same type appears as a doubly nested mess of SELECT TYPE statements. However the Visitor (also called Bridge) design pattern provides a way to implement double dispatch in a single dispatch language. Whether the extra complexity is better than the tangle of SELECT TYPE depends on the use case and the eye of the developer. And of course, next generation Generics features in the language will also reduce the need for such nested SELECT TYPE's in the future. But that's a ways off. |
Something so we can avoid these annoying nested
select type
blocks.So if you want to check if several variables are integers:
Or if you want to check if a variable is any integer kind:
Or any numeric kind:
And all together:
The text was updated successfully, but these errors were encountered: