我试图从子程序推广函数调用.所以我的想法是这样的
if (case1) then
call MainSubroutine1(myFun)
elseif (case2)
call MainSubroutine2(myFun)
end if
do i = 1,4
data = myFun(i)
end do
我意识到这有点模糊,但我不确定这是否可行.
谢谢,
约翰
编辑1/31/14 7:57 AM
对于我措辞的模糊方式,我感到很遗憾.我正在想类似于@haraldki所做的事情,但我希望我可以在MainSubroutine1和MainSubroutine2中定义一个匿名函数,并将该定义传递给主代码.
这是因为myFun依赖于不同的拉伸分布(Gaussian和Fermi-Dirac),我不希望有一个只调用一个常量抛出函数的函数.
这可能吗?
再次感谢你.
约翰
最佳答案 你问的答案很简单:不,你不能返回一个匿名函数.这是因为正如@VladimirF在评论中所说,Fortran中没有匿名函数.正如评论所说的那样,程序指针是完全可以接受的.
随后进行了大规模推测,这有望成为避免匿名功能要求的一种方式.
我推断你想做点什么
subroutine MainSubroutine1(fptr)
procedure(func), pointer, intent(out) :: fptr
! Calculate parameterization for your "anonymous" function
fptr => anon_parameterized
contains
real function anon_parameterized(i)
integer, intent(in) :: i
! Use the parameterization
anon_parameterized = ...
end function
end subroutine
你不想这样做
subroutine MainSubroutine1(fptr)
procedure(func), pointer, intent(out) :: fptr
fptr => Gaussian
end subroutine
real function Gaussian(i)
integer, intent(in) :: i
! Calculate parameterization
Gaussian = Gaussian_parameterized(i, ...)
contains
function Gaussian_parameterized(i, ...)
integer, intent(in) :: i
!... other intent(in) parameters
end function
end subroutine
请注意,这些不是内部的,因为传递指向其他内部事物的指针尚未得到很好的实现(作为F2008功能),并且很棘手.将指针传递给内部过程以获取主机关联会让我感到害怕.
如果我的推论是正确的,那么就有可能使用模块变量来存储参数化,再次允许最终的“参数化”调用不在MainSubroutine1的内部.
但是,您可能希望避免使用模块变量,在这种情况下,您可以考虑将参数化与函数调用一起传递:
procedure(func), pointer :: myFun => null()
if (case1) then
call MainSubroutine1(myFun)
else if (case2)
call MainSubroutine2(myFun)
end if
if (.not.associated(myFun)) STOP ":("
data = myFun(1, par1, par2)
啊,但你不确定myFun所需的非参数化函数的参数是什么,所以你的界面都被打破了.不是吗?
然后导致多态性.
module dists
type, abstract :: par_type
end type par_type
type, extends(par_type) :: par_gaussian
real :: mu=5.2, sigma=1.2
end type par_gaussian
type, extends(par_type) :: par_fermi_dirac
real :: eps=11.1, mu=4.5
end type par_fermi_dirac
abstract interface
real function func(i, pars)
import par_type
integer, intent(in) :: i
class(par_type), intent(in) :: pars
end function func
end interface
contains
real function gaussian(i, pars)
integer, intent(in) :: i
class(par_type), intent(in) :: pars
select type (pars)
class is (par_gaussian)
print*, "Gaussian", pars%mu, pars%sigma
gaussian = pars%mu+pars%sigma
end select
end function gaussian
real function fermi_dirac(i, pars)
integer, intent(in) :: i
class(par_type), intent(in) :: pars
select type (pars)
class is (par_fermi_dirac)
print*, "Fermi-Dirac", pars%eps, pars%mu
fermi_dirac = pars%eps+pars%mu
end select
end function fermi_dirac
subroutine sub1(fptr, pars)
procedure(func), pointer, intent(out) :: fptr
class(par_type), intent(out), allocatable :: pars
fptr => gaussian
allocate(par_gaussian :: pars)
end subroutine sub1
subroutine sub2(fptr, pars)
procedure(func), pointer, intent(out) :: fptr
class(par_type), intent(out), allocatable :: pars
fptr => fermi_dirac
allocate(par_fermi_dirac :: pars)
end subroutine sub2
end module dists
program prog
use dists
implicit none
class(par_type), allocatable :: pars
procedure(func), pointer :: myfun
call sub1(myfun, pars)
print*, myfun(i, pars)
call sub2(myfun, pars)
print*, myfun(i, pars)
end program prog
不过,这都是猜测.