Fortran - 从子例程返回匿名函数

2023-12-02

我试图概括子例程的函数调用。所以我的想法是这样的

if (case1) then
   call MainSubroutine1(myFun)
elseif (case2)
   call MainSubroutine2(myFun)
end if

do i = 1,4
   data = myFun(i)
end do

我意识到这有点模糊,但我不确定这是否可能。

谢谢你,

John


编辑 2014 年 1 月 31 日 7:57


对于我的措辞含糊不清,我深表歉意。我在想类似于 @haraldki 所做的事情,但我希望我可以在 MainSubroutine1 和 MainSubroutine2 中定义一个匿名函数,并将该定义传输到主代码中。

这是因为 myFun 取决于不同的拉伸分布(高斯分布和费米狄拉克分布),并且我不希望有一个函数只调用一个抛出常量的函数。

这可能吗?

再次感谢你。

John


您问题的答案很简单:不,您不能返回匿名函数。这是因为,正如 @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

不过,这都是猜测。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Fortran - 从子例程返回匿名函数 的相关文章

随机推荐