functional-programming - Fortran是纯功能性语言吗?

标签 functional-programming fortran programming-languages fortran90 paradigms

我了解某些语言结合了编程中许多不同范例的元素。有人告诉我Fortran是一种功能语言的示例,但是我对它是否纯粹是功能性感到有些困惑,因为它似乎主要用于数学功能,但是我也读到它是也可以将面向对象的编程应用于Fortran,这是否是某种混合形式?

最佳答案

“对于它是否纯粹是功能性,我有点困惑,因为它似乎主要用于数学函数”
这似乎是对术语“纯功能”的含义的误解,也可能是对术语“数学功能”的含义的误解。
数学功能
mathematical function是输入和输出之间的映射:

在数学中,函数是集合之间的一种关系,该关系与第一个集合的每个元素恰好与第二个集合的一个元素相关联。

在编程语言的上下文中,函数的输入是其参数,而输出是其返回值,因此例如像

def greeting(name):
    return 'Hello, ' + name

在Python中被认为是数学函数,而类似
def print_square(x):
    print(x ** 2)
    return None

不被视为数学函数。这里要注意的是,计算本质上是否是数学与它是否是数学意义上的函数无关。 print_square做一些算术运算,比greeting更像数学。但是greeting是数学函数,而print_square不是。
greeting是数学函数,因为它是从字符串集到字符串集的映射,并且可以通过将哪些输入与哪些输出相关联来描述该函数。完整写出映射将花费无数行,但是映射就像:
'Alice'   → 'Hello, Alice'
'Bob'     → 'Hello, Bob'
'Charles' → 'Hello, Charles'
'####'    → 'Hello, ####'
''        → 'Hello, '
...

第一组中的每个元素(即所有字符串的集合)都与第二组中的一个元素正好关联,因此greeting满足数学函数的定义。
相反,print_square不是数学函数,因为它不能通过输入到输出的映射来描述:
12 → None
4  → None
...

这些映射(从整数集到{None}集)没有正确定义print_square的作用,这是因为它计算输入和prints it to the console的平方。
为了避免与“数学上起作用的函数”混淆,最好使用计算术语“ pure function”:

...纯函数是数学函数的计算类似物。

因此,为了表达您的意见,即Fortran“似乎主要用于数学函数”,Fortran主要用于进行数学计算,但这不是“数学函数”的含义。
纯函数式编程
purely functional编程语言是其中所有计算均由纯函数完成的一种语言:

在计算机科学中,纯函数式编程通常指定一种编程范例...,它将所有计算视为对数学函数的评估。也可以通过禁止更改状态和可变数据来定义纯功能编程。

请注意,仅使用一种编程语言就不能编写纯函数。这个定义说,所有计算都必须由纯函数来完成,语言才能具有纯函数的资格。
Fortran是纯功能性语言吗?不它不是。根据输入和输出之间的映射,Fortran中的子例程可以做其他事情,而不是返回值。 Fortran中的计算可以通过状态更改和可变数据来完成。一个例子就足够了:这个例子来自Rosetta Code
subroutine hs(number, length, seqArray)
  integer, intent(in)  :: number
  integer, intent(out) :: length  
  integer, optional, intent(inout) :: seqArray(:)
  integer :: n
 
  n = number
  length = 1
  if(present(seqArray)) seqArray(1) = n
  do while(n /= 1)
    if(mod(n,2) == 0) then
      n = n / 2
    else
      n = n * 3 + 1
    end if
    length = length + 1
    if(present(seqArray)) seqArray(length) = n
  end do
end subroutine

变量n显然是可变的,因为其状态在循环中发生了变化。同样,数组seqArray是可变的,它既是子例程的输入又是其输出,并且该子例程更改了数组的状态。因此,此子例程未定义纯函数,而是使用“状态更改和可变数据”,这是纯函数语言的定义所禁止的。
因此,子例程hs即使其执行的计算本质上是mathematical,也没有定义“数学函数”。
命令式编程
Imperative programming是:

...一种使用更改程序状态的语句的编程范例。 ...命令式程序由计算机执行的命令组成。

上面显示的Fortran子例程符合这两个定义:它使用改变计算机执行程序状态的语句或命令。因此,Fortran是命令式编程语言。
请注意,与Wikipedia的“纯功能”定义不同,即使不是以这种方式进行所有计算的语言,也可能必须使用一种语言。因此,尽管可以在Fortran中编写纯函数,而这些纯函数无法通过更改程序状态来工作,但是Fortran势在必行;也许不是“绝对必要”。
“什么”与“如何”
“这意味着fortran仅描述了'如何'做某事,而不是'它试图做的事'?”
人们经常说命令式程序是说“应该”完成计算的程序,而声明式程序只说“应该做什么”。甚至维基百科says so

命令式编程着重于描述程序的运行方式。
该术语通常与声明性编程相反,后者声明性编程侧重于程序应完成的工作,而不指定程序应如何获得结果。

那么,Fortran代码是描述程序“应该”如何做某事,还是应该完成“什么”?
n = n / 2这样的语句是告诉计算机执行某项操作的命令。在计算机执行命令之前有一个程序状态,此后又有一个不同的程序状态。语句n = n / 2还告诉计算机“如何”执行命令:将n的当前值除以2,然后将结果存储在变量n中。因此,根据“如何” /“什么”的区别,Fortran是命令性的,而不是声明性的。
但您可能会争辩:n = n / 2表示我们要实现的目标。一个新的程序状态,其中n保留旧状态的值并除以2。您会说对了,它的确如此,至少对于阅读它的人而言。
这表明“如何” /“什么”的区别太模糊,以至于不能用作定义一种语言是命令式还是声明式的定义。这只是这些范例之间的松散描述对比,而不是任何一个范例的定义。要确定一种语言是强制性语言还是纯功能性语言,还是其他任何范式,您应参考该范式的可服务定义。

关于functional-programming - Fortran是纯功能性语言吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59924055/

相关文章:

javascript - 一个叫做 struggle 的高阶函数怎么样?

compiler-construction - 无法执行wfc386没有此类文件或目录-Watcom Fortran IDE

fortran - 在 OpenMP 区域内调用内部子程序

programming-languages - 值得努力学习 D 吗?

java - 如何以函数式风格多次写入 "if optional is empty, call next method returning optional, if not return this non-empty optional"?

Scala Cats 或 Scalaz 类型类 scanLeft 等

javascript - 将函数包装到另一个函数中

fortran - `DO` 循环如何在 Fortran 66 中工作?

ruby - 为什么在 Ruby 中将 0 视为 True?

常见的基于堆栈的 VM 字节码优化?