Reputation: 43
I'm thinking of using the submodule feature in Fortran and have setup a small test example. I have two questions related to their usage. Below is the example code:
module points
type :: point
real :: x, y
end type point
interface
module function point_dist(a, b) result(distance)
type(point), intent(in) :: a, b
real :: distance
end function point_dist
end interface
end module points
submodule (points) points_a
contains
module procedure point_dist
distance = sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
end procedure point_dist
end submodule points_a
This works and in my program I can just use it as such:
program test
use points
real(kind(1.0D0)) :: result
type (point) :: p1, p2
p1%x = 1
p1%y = 1
p2%x = 2
p2%y = 2
result = point_dist(p1, p2)
write(*,*) result
end program test
1) However I was wondering if it is possible to have two submodules that use the same interface but provide different outcomes. This has some uses where we have different formulae calculating the same physical quantity. Below is how I imagined it would work, even though it does not.
module points
type :: point
real :: x, y
end type point
interface
module function point_dist(a, b) result(distance)
type(point), intent(in) :: a, b
real :: distance
end function point_dist
end interface
end module points
submodule (points) points_a
contains
module procedure point_dist
distance = sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
end procedure point_dist
end submodule points_a
submodule (points) points_b
contains
module procedure point_dist
distance = 2.0*sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
end procedure point_dist
end submodule points_b
I get an error in the program as I only have the statement use points
and it complains about duplicate definitions of point_dist
. Is is possible to specify which submodule I want to use?
2) I also looked but couldn't find out if it is possible to use the same module level interface for different procedures inside the same submodule. In my head it would be something like:
module points
type :: point
real :: x, y
end type point
interface
module function point_dist(a, b) result(distance)
type(point), intent(in) :: a, b
real :: distance
end function point_dist
end interface
end module points
submodule (points) points_a
contains
module procedure (type=point_dist) point_dist_a
distance = sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
end procedure point_dist_a
module procedure (type=point_dist) point_dist_b
distance = 2.0*sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
end procedure point_dist_b
end submodule points_a
Although I realise that this could lead to some quite misleading and hard to follow code.
(I'm using gfortran 8.3.0 on OS X)
Upvotes: 0
Views: 340
Reputation: 8546
1) However I was wondering if it is possible to have two submodules that use the same interface but provide different outcomes. This has some uses where we have different formulae calculating the same physical quantity.
If this were possible, how were you plannig to make use of it? I mean, if you have two different implementations avaliable for a function point_dist
thay may yield different outcomes, you wouldn´t want to mismatch them, would you?
If you want them to have the same name, you (and the compiler) must be able to identify which one you're calling. This is usually done with function overloading. In Fortran, you may have a generic interface
. BUT the dispatched funtions MUST differ in their interface (argument types and/or quantity, position, among other rules). You know, how would anyone else know which of the two you do mean?
2) I also looked but couldn't find out if it is possible to use the same module level interface for different procedures inside the same submodule.
As I said, an interface can indeed encapsulate multiple procedures, if they are distinguishible.
module points
type :: point
real :: x, y
end type point
interface point_dist
module function point_dist_a(a, b) result(distance)
type(point), intent(in) :: a, b
real :: distance
end function
module function point_dist_b(a, b, k) result(distance)
type(point), intent(in) :: a, b
real, intent(in) :: k
real :: distance
end function
end interface
end module points
submodule (points) points_a
contains
module procedure point_dist_a
distance = sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
end procedure point_dist_a
end submodule points_a
submodule (points) points_b
contains
module procedure point_dist_b
distance = k*sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
end procedure point_dist_b
end submodule points_b
Testing:
program test
use points
real(kind(1.0D0)) :: result
type (point) :: p1, p2
p1%x = 1
p1%y = 1
p2%x = 2
p2%y = 2
result = point_dist(p1, p2)
write(*,*) result
result = point_dist(p1, p2, 2.0)
write(*,*) result
end program test
As an end note, submodules
have absolutely nothing to do with all this.
Upvotes: 3