subroutine generic_name(...)
...
end subroutine
subroutine algorithm(..., proc)
...
procedure(generic_name) :: proc
...
end subroutine
But since you cannot pass generic intrinsic procedures as actual arguments, the same should hold true for custom generic procedures. And the use of specific names for intrinsic functions is deprecated anyway, so …
In an ideal world, where new features are implemented in less than 20 years , a variable of enumeration type could be passed in lieu of the specific procedure.
The current workaround for this is to define a contained procedure (or some other procedure) that references the generic with the appropriate arguments, and then use that contained procedure as the actual argument or in the procedure pointer assignment. (This was not allowed in f90, but it was allowed later, I think in f2003.)
It seems like that approach could be simplified somehow with just a single pointer assignment type of expression, the purpose of which is to define a local alias to the specific routine. This new syntax could then be extended to the new user-defined generic procedures with their anonymous specific versions, and everything could be consistent.
Apologies, my example above was incorrect. An additional keyword is included to disambiguate. I.e. select generic type.
Correct.
Correct. We’re hopeful that the “standalone template procedure” and requirement/require features can reduce the verbosity to a reasonable level. I.e.
subroutine sub(T, U, V, op1, op2, ...)(dummy, args, ...)
require these_work_together(T, U, V, op1, op2, ...)
type(T), intent(in) :: dummy
type(U), intent(out) :: args(:)
...
end subroutine
This is not allowed. Only specific procedures can do those things, and there is no way to specify one of the specific procedures generated from a generic procedure.
The current intrinsic functions that can result in output of multiple types use some kind of mold argument to select the desired output type. This is sort of a generic output type for those functions. For example, the result of transfer(source, mold) is a value with the type of mold, but it works for arbitrary types, even user-defined types. This functionality is not currently available for programmers to use to write similar “generic” functions. There is also the convention used in several intrinsic functions that a kind argument specifies the kind of the function value. An example is size(array,kind=ik), which returns an integer value of kind ik. This is another potentially useful feature available only to intrinsic functions and not exposed to the programmer for use within user-written functions.
I am afraid I am one of those who view all recent attempts at adding generic/template capabilities to Fortran as misguided. The problem that these capabilities are seeking to solve is a) not well-understood and b) quite orthogonal to the current use of a Fortran compiler (to produce fast code, for a variety of processors, using all available resources efficiently, for a well-specified task). I took the lesson from the success of Unix that small tools, designed to be combinable, are better than one monolithic, fixed way of getting work done.
Fortran has already grown to the point that it is very unusual for anyone to have a complete grasp of it. Some people think that the last capitalised version was the perfect form, I sometimes see their point but disagree. But it can’t be far.
The largest reason generics are such an important topics is simple: data containers*. If Fortran standard specified basic data structures such as a variable-size list and a hashmap (like Python, Julia, …), I think 99% use cases of the generics would disappear**. A very efficient implementation of such structure could be provided by a compiler, and likely we would see it appear faster in compilers than implementation for generics.
That being said, this is one of the threads I was the most happy to read in the history of this board.
Yuck to that commitee member. (Nothing personal, I do not know them, but that feels extremely unproductive, and any sentence alike “you should code this way” triggers me.) But big thanks to YOU for being a push in the good direction despite the environment you have to work in.
[ * There are also ways to utilize generic function for configurability of the program. Using generics instead of polymorphism guarantees easy inlining and good performance. ]
[ ** People who write libraries that need to be implement for all real and integer kinds will disagree here and rightfully so. But as an end-user does not feel this pain, he just knows stdlib will work for any numeric type available. ]
Based on previous comments in this and other threads I’ve come to the opinion that its the folks whose primary focus is creating libraries (either open-source or commercial) are the ones “driving the bus” when it comes to what eventually becomes part of the standard. This is the only way I can explain some of (to me) the strange additions to the language that (based on my experience) would rarely if ever be used in a standalone scientific application. I’m somewhere in the middle ground like @themos about generics (particularly templates). Yes there is a need for them for some use cases but I think those cases could have been covered by a properly designed (or at least working) PDT facility. In general, I think the need for something like templates in writing say a CFD code, FEM code or shallow-water solver is pretty low. People forget that one of the reasons templates became popular in C++ is because they (in the form of expression templates) where the only way the compilers could optimize away the creation of internal temporary memory due to exessive operator overloading and allow performance in scientific applications that could rival Fortran. I think you can make the case that it was expression templates that saved C++ from being a niche language.
Not an English native either but I always thought that is is exactly from casting. Like you want to provide “shape” for the type without it’s “content”.
This is already possible with function overloading, but of course requiring code duplication.
Awesome thanks! That didn’t occur to me, I thought it has something to do with “old”, but I didn’t know what the “m” standed for. The noun “mold” makes a lot more sense!
The allocate statement already has a mold specifier, as described here. An example of its use
is
implicit none
integer, allocatable :: a(:), b(:), c(:)
a = [2, 4, 6]
allocate (b, c, mold=a)
print*, shape(b), shape(c) ! 3 3
print*, b, c ! gives random output since b and c are allocated but not set
end
The Fortran Standard Library is another such example where mold is used for the same purpose (among other places, see this recent one for example).
That said, I would like to send a shout out to @everythingfunctional@certik and all those involved in desiging the Fortran generics for the amazing work and for keeping the community involved!
Maybe all of us like some details more and some less, but overall, it’s a very strong design imho, can’t wait to start working with Fortran templates and generics!
Just $0.02 on the same topic, I think that generic procedures are to procedures what parameterized derived types are to derived types, and in that respect, I don’t see why a kind argument should not be possible:
generic function my_size (a, ik)
integer, intent(in), kind :: ik ! must be default integer
integer(kind=ik) :: my_size
end function my_size
PDTs already allow this syntax so it would be a relatively straightforward extension But as said, mold is another good carryover from the current Standard.
We looked at the issue of large numbers of unused module and internal routines. It looks as if the compilers we tested - gfortran and ifx, generate all the code for module subprograms but only the code needed for internal subprograms.