Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Module procedures and abstract interfaces

164 views
Skip to first unread message

Rudi Gaelzer

unread,
Apr 5, 2022, 12:42:03 PM4/5/22
to
I have a comment/question regarding the mechanism provided by the standard to store a number of identical interfaces and the level of verbosity involved.

Say I write a bunch of functions, all with the same interface and the same function result. The only difference involved are the methods employed to evaluate the same function.

One of the things I can do in this case is to create a module, with a single INTERFACE block containing the interfaces of the different implementations inside it. If I declare the interfaces with the "module function" keywords I can write the source codes inside a submodule, with the header "module procedure" for each individual function code.

This works very well and is very useful. The only irksome thing here is that the interface block inside the module ended up containing several almost identical declarations, whose only differences were the actual names of the various functions.
Then I thought of declaring an abstract interface and then only include the list of the proper names inside the interface block with the PROCEDURE(<abst inter>) declaration, in order to achieve a lower verbosity level. But it seems that the standard forbids this alternative.

This is the sample code:
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
MODULE module_procedures_abstract_interface
use, intrinsic :: iso_fortran_env, only: dp => real64
implicit none

ABSTRACT INTERFACE
function fun_2_args(x, y)
import :: dp
real(dp) :: fun_2_args
real(dp), intent(in) :: x, y
end function fun_2_args
END INTERFACE

! INTERFACE ! version 1
! PROCEDURE(fun_2_args) :: fun1, fun2
! END INTERFACE

INTERFACE ! version 2
module function fun1(x,y)
! import :: dp
real(dp) :: fun1
real(dp), intent(in) :: x, y
end function fun1
!***
module function fun2(x,y)
! import :: dp
real(dp) :: fun2
real(dp), intent(in) :: x, y
end function fun2
END INTERFACE
END MODULE module_procedures_abstract_interface
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Compilation with version 1 commented works all right, but if I uncomment version 1, error messages appear. The intel compiler gives:
$> ifort -c module_procedures_abstract_interface_MOD.f90
module_procedures_abstract_interface_MOD.f90(16): error #6651: The PROCEDURE specification is allowed only if the interface-block has a generic-spec.
PROCEDURE(fun_2_args) :: fun1, fun2
---^
compilation aborted for module_procedures_abstract_interface_MOD.f90 (code 1)

So it seems to me that I only have the more verbose solution allowed.
Or am I missing something?

FortranFan

unread,
Apr 5, 2022, 2:29:04 PM4/5/22
to
On Tuesday, April 5, 2022 at 12:42:03 PM UTC-4, rgae...@gmail.com wrote:

> ..
> So it seems to me that I only have the more verbose solution allowed.
> Or am I missing something?

@rgae...@gmail.com,

First, you may want to post this at Fortran Discourse also:
https://fortran-lang.discourse.group/

Two benefits with this:
1) you are dealing with modern Fortran code specifically and it will be much easier for you and anyone else interested to read and follow the details,
2) you will get a wider engagement and feedback on such matters

Your concerns with verbosity are valid, you may bring it up at GitHub J3-Fortran proposals site by posting a thread under Issues and see where that leads:
https://github.com/j3-fortran/fortran_proposals

In the mean time, note a slightly modified approach you can consider is with procedure pointer and you might find it is a tad less verbose in terms of repeated INTERFACE declarations - see below (with a simple function example):

module implementations_m
contains
function fun1(x,y) result(z)
integer, intent(in) :: x
integer, intent(in) :: y
integer :: z
z = x + y
end function
function fun2(x,y) result(z)
integer, intent(in) :: x
integer, intent(in) :: y
integer :: z
z = 2*x + 3*y
end function
end module
module m
use implementations_m
abstract interface
function Ifun(x,y) result(z)
integer, intent(in) :: x
integer, intent(in) :: y
integer :: z
end function
end interface
procedure(Ifun), pointer :: fun => null() ! or set to default
contains
subroutine setfun( fun_name )
character(len=*), intent(in) :: fun_name
select case ( fun_name )
case ( "fun1" )
fun => fun1
case ( "fun2" )
fun => fun1
case default
! error stop?
end select
end subroutine
end module
use m
call setfun( "fun2" )
print *, fun(3, 4)
end

So with above, your SUBMODULE approach is eschewed and the interface and implementation are separated out in a way as suggested since Fortran 90 revision.

To reiterate, I recommend you initiate a dialogue on this at Fortran Discourse.

Rudi Gaelzer

unread,
Apr 5, 2022, 6:15:02 PM4/5/22
to
On Tuesday, April 5, 2022 at 3:29:04 PM UTC-3, FortranFan wrote:
> On Tuesday, April 5, 2022 at 12:42:03 PM UTC-4, rgae...@gmail.com wrote:
>
> > ..
> > So it seems to me that I only have the more verbose solution allowed.
> > Or am I missing something?
> @rgae...@gmail.com,
>
> First, you may want to post this at Fortran Discourse also:
> https://fortran-lang.discourse.group/
>
> Two benefits with this:
> 1) you are dealing with modern Fortran code specifically and it will be much easier for you and anyone else interested to read and follow the details,
> 2) you will get a wider engagement and feedback on such matters

Will do that, thanks for the suggestion.

>
> Your concerns with verbosity are valid, you may bring it up at GitHub J3-Fortran proposals site by posting a thread under Issues and see where that leads:
> https://github.com/j3-fortran/fortran_proposals

Might do that as well, thanks.
Yes, I thought about using a procedure pointer. Your setfun routine is a nice idea, will think about it as well.
I guess that with submodules, there is no way the standard will allow my imagined implementation. In this case, your suggestion works better for my objectives, as long as I only declare the pointer and setfun as public and all the rest as private, in order to achieve the desired data abstraction.
0 new messages