Fortran 中的过程指针

2024-01-19

假设我有以下单参数双精度函数的抽象接口

module abstract

  abstract interface
     function dp_func (x)
       double precision, intent(in) :: x
       double precision :: dp_func
     end function dp_func
  end interface

end module abstract

在另一个模块中,我定义了两个函数,一个是简单的函数g类型的dp_func还有一个更复杂的f

module fns

 contains
 double precision function f(a,b,x)
   double precision, intent(in)::a,b,x
   f=(a-b)*x 
 end function f

 double precision function g(x)
   double precision, intent(in)::x
   g=x**2 
 end function g
end module fns

现在指向g可以创建如下

program main
use abstract,fns
procedure(dp_func), pointer :: p
double precision::x=1.0D0, myA=1.D2, myB=1.D1, y
p => g
y=p(x)
end program main

但是如何创建一个指向f(myA,myB,x),即f在固定值a and b,它可以被视为只有 1 个参数的函数,即dp_func类型? 最终结果我希望能够写出类似的东西

p=>f(myA, myB, )
y=p(x)

下面的评论表明函数闭包 https://en.wikipedia.org/wiki/Closure_(computer_programming)不是 Fortran 标准的一部分,包装函数将是一个可能的解决方案。然而,包装器必须被初始化,这导致最终用户可能忘记调用初始化器。如何以干净、透明的方式做到这一点?

EDIT发布这个问题并用谷歌搜索“闭包和 Fortran“,我找到了这个例子

我以图片形式呈现以强调突出显示。这是在在线课程中介绍的。但我怀疑这种隐式参数设置是否是一种好的编程实践。事实上,像这样的悬空变量z在这个例子中是完美的错误来源!


您可以使用内部函数来包装您的函数,例如

program main
  use abstract
  use fns
  implicit none
  
  procedure(dp_func), pointer :: p
  double precision :: x, myA, myB, y
  
  x = 1.0D0
  myA = 1.D2
  myB = 1.D1
  
  p => g
  y=p(x)
  
  p => f2
  y = p(x) ! Calls f(1.D2, 1.D1, x)
  
  myA = 1.D3
  myB = 1.D2
  
  y = p(x) ! Calls f(1.D3, 1.D2, x)
contains
  double precision function f2(x)
    double precision, intent(in) :: x
    write(*,*) myA, myB
    f2 = f(myA,myB,x)
  end function
end program main

给定作用域中的内部函数可以使用该作用域中的变量,因此它们可以像闭包一样起作用。

隐式使用myA and myB在内部函数中f2很可能是编程错误的根源,但是,只要范围f2仍在范围内,此行为与lambda其他语言中的函数,例如等效的 python lambda:

f2 = lambda x: f(myA,myB,x)

正如 @vladimirF 所指出的,一旦范围f2超出范围(例如,如果指向f2被存储并且过程在哪里f2被声明返回)任何指向f2将会失效。这可以在这段代码中看到:

module bad
  use abstract
  use fns
  implicit none
contains

function bad_pointer() result(output)
  procedure(dp_func), pointer :: output
  
  double precision :: myA,myB
  
  myA = 1.D2
  myB = 1.D1
  
  output => f2
contains
  double precision function f2(x)
    double precision, intent(in) :: x
    write(*,*) myA, myB
    f2 = f(myA,myB,x)
  end function
end function

end module

program main
  use abstract
  use fns
  use bad
  implicit none
  
  procedure(dp_func), pointer :: p
  double precision :: y,x
  
  p => bad_pointer()
  x = 1.D0
  y = p(x)
end program

注意:对于这个简单的情况,上面的代码可能运行良好,但它依赖于未定义的行为,因此不应使用。

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

Fortran 中的过程指针 的相关文章

  • 关于for循环中的fortran continue语句的问题

    我正在分析 Fortran 代码并有一个简单的问题 我想知道下面代码中 100 和 200 处的 继续 语句的作用 它会增加 i 和 j 计数器吗 如果是这样的话 不会if not flg 那么条件包含flg循环中 flg 的 最后一个值
  • 在 Go 中执行字节数组

    我正在尝试在 Go 程序中执行 shellcode 类似于使用其他语言执行此操作的方式 示例 1 C 程序中的 Shellcode https stackoverflow com questions 16626857 shellcode i
  • 指定 gfortran 应该在其中查找模块的目录

    我目前基于模块来编译程序 例如主程序foo这取决于模块bar 如下 gfortran c bar f90 gfortran o foo exe foo f90 bar o 当foo f90 and bar f90位于同一目录中 如何指定 g
  • Javascript 函数指针,以参数作为函数中的参数

    不确定标题的措辞是否正确 或者是否有更好的表达方式 但我认为还可以 无论如何 到目前为止我了解以下内容 a b a b c foo 其中 foo 是在其他地方定义的函数 不接受任何参数 只会导致函数 a b 使用上述参数运行 然后可以在函数
  • 如何在Fortran代码中将二维数组转换为一维数组?

    如何将 r i j 转换为一维数组以便可以轻松地对数字进行排序 program sort implicit none character CN 8 O 7 integer j iconf nconf integer i nbins t in
  • f951 错误:无法识别的命令行选项

    我在linux上 正在编译以下内容 mpif90 shared source F90 object1 o object2 o L some path Qoption link rpath some path I some path lhdf
  • 为什么 std::function 不是有效的模板参数,而函数指针却是?

    我已经定义了名为的类模板CallBackAtInit其唯一目的是在初始化时调用函数 构造函数 该函数在模板参数中指定 问题是模板不接受std function作为参数 但它们接受函数指针 为什么 这是我的代码 include
  • 如何读取 Fortran 中内容不以空格分隔的 2D 文件

    我有一个矩阵存储在文件 number txt 中 如下所示 12323456 54254311 76534522 我如何在 Fortran 中读取这样的矩阵 结果将是 1 2 3 2 3 4 5 6 5 4 2 5 4 3 1 1 7 6
  • 使用 MacLaurin 展开的 Fortran Sine 函数的微小差异

    我正在用 Fortran 创建一个程序 它接受以弧度表示的 sin x 的 x 然后是要计算的项数 这是我的程序 Sine value using MacLaurin series program SineApprox implicit n
  • 是否可以创建一个指向函数的“new”运算符/构造函数的函数指针?

    如果我想要参数化创建一个对象 我当然可以创建一个函数 在特定类上调用 new 并传递一个指针 我想知道是否可以跳过该步骤并将函数指针传递给new运营商本身 boost lambda 提供函数包装器new and delete http ww
  • 指针的 Fortran 副本

    我有一个包含指针 p 的 var 类型 我需要将 var 复制到与 var 类型相同的另一个变量 var1 上 通过执行 var1 var 在引号中 因为我不知道这是否是正确的方法 请参见下文 在我的实现中 var 和 var1 被传递给一
  • C 中的函数指针和枚举

    我正在寻找一种链接函数指针和枚举的奇特方法 就我而言 我有一个消息队列 其中包含事件 ID 和与事件关联的一些数据 一些简单的伪代码 event eid data switch eid case eid1 handler1 data bre
  • Fortran 递归分段错误

    我必须设计并实现一个 Fortran 例程来确定方格上簇的大小 并且递归地编写子例程似乎非常方便 然而 每当我的晶格大小超过某个值 大约 200 边 时 子例程就会始终出现段错误 这是我的集群检测例程 RECURSIVE SUBROUTIN
  • 我可以使用 lambda 函数或 std::function 对象来代替函数指针吗?

    我有一个需要使用的库 它定义了以下内容 typedef void CallbackFunction const int i 并且有一个注册回调的函数 如下所示 void registerCallback CallbackFunction p
  • 这些双精度值如何精确到小数点后 20 位?

    当精度是一个问题时 我正在测试一些非常简单的等价错误 并希望以扩展双精度执行操作 这样我就知道答案在 19位数字中 然后以双精度执行相同的操作 其中第 16 位会有舍入误差 但不知何故 我的双精度算术保持了 19 位精度 当我在扩展双精度中
  • Fortran :: (1) 处 OPEN 语句中存在语法错误

    我试图通过 顽固测试 来测试我的密码算法 http stat fsu edu pub diehard http stat fsu edu pub diehard 我意识到我的输入文件必须是未格式化的直接访问文件 所以我尝试用 Fortran
  • 在 VSCode Fortran 调试中检查从另一个模块导入的变量

    我正在调试一些包含许多 Fortran 模块的代码 其中一些模块彼此共享变量 不幸的是 带有 VScode 的 gdb 在调试时似乎无法检查导入的变量 目前 当我需要检查导入的变量时 唯一的方法是停止调试 并手动更改代码以包含等于导入变量的
  • 使用 Fortran 90 正确读取输入文件中的注释行

    据我了解 Fortran 在从文件读取数据时 会跳过以星号 开头的行 假设它们是注释 好吧 我似乎在用我创建的一个非常简单的程序实现这种行为时遇到了问题 这是我的简单 Fortran 程序 1 program test 2 3 intege
  • Fortran 指针数组

    同样 Fortran 中的指针数组 好吧 我有一个派生类型 type t context pointer type t context pointer p ctx end type t context pointer 当我在主程序中执行以下
  • Fortran 子例程返回错误值

    嘿 我正在开发一个 Fortran 程序 遇到了一个奇怪的问题 当我尝试在调用特定子例程之前直接输出数组的某些值时 我得到了正确的值 然后 我尝试在启动子例程时输出同一数组的一些值 它们都是 0 我最终在子例程之后输出数组的值 并且这些值回

随机推荐