New generic procedures feature

That makes sense, since the module subprograms might be used elsewhere, but one can think of the CONTAINed ones as statement functions but proper.

When it comes to submodules, though, gfortran has the flaw of propagating the access (public|private) to the object files. So even if your generic is not intended to be used by the outside world, you have to either make it public or place the submodule alongside the module:

! gf_generic_mod.f90
module mod1
    implicit none
    private

    interface g
        module procedure p1
        module procedure p2
    end interface

    interface
        module subroutine do_print()
        end subroutine
    end interface

! #ifdef __GFORTRAN__
!     public g
! #endif

    public do_print

contains
    subroutine p1()
        print *, 'Hello world!'
    end subroutine
    subroutine p2(name)
        character(*), intent(in) :: name
        print *, 'Hello '//name//'!'
    end subroutine
end module
! gf_generic_smod.f90
submodule (mod1) sm_generic
    implicit none

contains
    module procedure do_print
        call g()
        call g('John')
    end procedure
end submodule
! gf_generic_main.f90
use mod1

implicit none

call do_print()
end
$ ifx gf_generic_mod.f90 gf_generic_smod.f90 gf_generic_main.f90 && ./a.out 
 Hello world!
 Hello John!

$ gfortran gf_generic_mod.f90 gf_generic_smod.f90 gf_generic_main.f90 && ./a.out 
/usr/bin/ld: /tmp/ccTwqsI7.o: in function `__mod1_MOD_do_print':
gf_generic_smod.f90:(.text+0x5): undefined reference to `__mod1_MOD_p1'
/usr/bin/ld: gf_generic_smod.f90:(.text+0x19): undefined reference to `__mod1_MOD_p2'
collect2: error: ld returned 1 exit status

@jwmwalrus
Exactly right!
Last year we replaced over 200 statement functions in fpt (which is written in Fortran) with internal functions with no change in performance. We tried module functions but the performances was dire. Now the code is slightly more respectable. :wink:

1 Like

That makes me think: how will the current generic feature blend in with PDTs?

module myarray_m

type :: myarray(arr_k, sz)
   integer, kind :: arr_k = 4
   integer, len :: sz
   real(kind=arr_k) :: data(sz)
contains
   procedure :: sum => arr_sum
end type

contains

function arr_sum(arr)
   type(myarray(sz=*, arr_k=*)) :: arr
   real(kind=kind(arr%data)) :: arr_sum
   arr_sum = sum(arr%data, kind=kind(arr%data))
end function

end module

@everythingfunctional How would the above pseudocode be implemented using the future generics feature?

Length type parameters can be assumed, so that is what the * still means for the parameter in this case. Since the compiler can not predict all of the valid kind type parameters for derived types, * cannot be used for that parameter. A list of the desired kind type parameters must be provided instead. In this case you at least have a convenient one that can be used. I.e.

generic function arr_sum(arr)
   type(myarray(sz=*, arr_k=real_kinds)) :: arr
   real(kind=kind(arr%data)) :: arr_sum
   arr_sum = sum(arr%data, kind=kind(arr%data))
end function
1 Like

@hkvzjal I suspect that the lack of templates is one of the reasons that the two are often the same. It wasn’t until I started writing libraries intended for use by others that I began to see the need for better support for generic programming. To put it differently, generic programming will make it easier to write libraries for others to use, which could make it more likely that library developers and application developers won’t necessarily be the same person.

I would shed the light from a different angle: I hope that whatever is decided and implemented at the end will make life easier for everyone, especially those who start their Fortran development journey as “application developer” and when realizing that they need to start working on a library to generalize their work would feel confident with a robust and simple-to-use syntax. As it is more likely that for a long time, this person will be the provider and consumer of his/hers codes, having the idea that eventually someone else will use his/her codes to develop on top of it, once proven useful and easy to use.

I’m just trying to say that this reasoning of “two (clear cut) personas” feels to me dangerous if placed at the heart of the design process for this specific feature; maybe as a happy consequence?

Apologies for digging up an old topic, but I think this one deserves at least a pinned status. So we have discussed the “generics” part of the proposal. Is there somewhere that the final (working) version of the “templates” can be seen? Is it much different to what was implemented currently in LFortran?