Fortran For Fun之纯函数 递归函数 逐元函数

Fortran中存在几种特殊的函数或子程序,这些函数或子程序需要在定义时特殊说明。主要有以下三种特殊程序

  • pure 程序 (纯程序)
  • recursive 程序 (递归程序)
  • elemental 程序 (逐元程序)

pure 程序

pure程序是不造成任何副作用的程序,即不能对输入参数以及模块中的数据进行修改,局部变量定义时不能初始化,也不能有save属性。很多函数都可以定义为pure 函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
program learn_pure
implicit none
if(add('foo','bar') == 'foobar') print*, 'pass'
contains
pure function add(a,b) result(c)
character(*), intent(in) :: a, b
character(:), allocatable :: c
c = a // b
end function add
end program learn_pure

该程序中定义了add纯函数,作用是将两个字符合起来,相当于 // 符号, 可以利用该函数重载 +,使文字合并操作与 python 一致。

结果

1
pass

recursive 程序

递归程序是不断调用自身的程序,它一定是一个纯程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
program learn_recursive
implicit none
integer :: n = 5
if(fact(n)==120) print*, 'pass'
contains
recursive function fact(n) result(r)
integer, intent(in) :: n
integer :: r
if(n<=0) then
r = 1
else
r = n*fact(n-1)
endif
end function fact
end program learn_recursive

该程序中定义了 fact 递归函数,求一个整数的阶乘。

结果

1
pass

elemental 程序

elemental程序的形参是标量,但输入参数可以是标量也可以是数组,如果是数组,则对数组中的每一个元素调用该程序。逐元程序也必须是纯函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
program learn_elemental
implicit none
character(2) :: s(3) = ['1 ','2 ','3 ']
if(all(to_int(s) == [1,2,3]).and.all(to_real(s) == [1.,2.,3.])) print*, 'pass'
contains
!=============================================================================
elemental function to_int(str)
character(*),intent(in) :: str
integer :: to_int
integer :: ios
read(str, * ,iostat= ios) to_int
endfunction to_int
!=============================================================================
elemental function to_real(str)
character(*),intent(in) :: str
real :: to_real
integer :: ios
read(str, * , iostat= ios) to_real
endfunction to_real
end program learn_elemental

该程序中定义了将字符转换为整数的逐元函数to_int和将字符转化为实数的逐元函数to_real。

结果

1
pass