6

在 Fortran 中,函数和子程序之间存在明显的区别:函数返回一个值,子程序不返回值。这会在两者之间引入一连串的差异。一个例子是调用语义:你可以像在其他语言中一样调用一个函数,但是为了调用一个子程序,你必须首先发出一个call语句。

随着在 Fortran95 中添加指针和数据类型,使任何子程序成为函数并保留子程序仅用于遗留似乎没有技术限制。函数可以返回零(您只返回一个虚拟整数)、一个或多个值(例如,您可以返回指向已分配类型实例的指针,例如 C++ STL 对)。

我错了吗?由于子程序具有某些功能而函数没有,我们是否仍然需要 Fortran 编程中的子程序?

4

5 回答 5

17

如果您搜索 comp.lang.fortran 档案,您会发现有关函数语义的讨论。IIRC 事实证明,标准中没有明确规定对于具有副作用的功能什么是允许的,什么是不允许的。

例如,编译器是否可以优化

x = foo(args) + foo(args)

进入

x = 2 * foo(args)

或者再举一个例子,考虑

x = y + foo(y)

如果 foo() 改变了 y 的值怎么办?请记住,Fortran 没有序列点的 C 概念。

一般来说,几位专家的建议是只使用纯函数,否则使用子例程。而且,这也是我自己遵循的建议。

于 2010-10-15T15:31:20.213 回答
6

我认为子程序不会去任何地方。大多数其他语言都允许返回值和不返回值的方法。我看不出这是一件坏事的任何理由。任何人都不应该被感动去改变一件事。

仅 Legacy 就表示,子例程将与 Fortran 一样持续存在。只要有 Fortran 存在,编写一个执行操作但不返回任何内容的方法就没有任何问题。

更新:

为什么说“麻烦”?有什么大不了的?我不同意在适当的情况下使用子例程是“麻烦”的想法。

Fortran 自 77 版(可能更早)以来一直区分函数和子例程。其他 C 系列语言也是如此。为什么会突然变得这么麻烦?即使是长期使用指针和对象的语言也有返回 void 的方法。

于 2010-10-15T11:27:10.503 回答
2

您正在尝试再次在 fortran 中对 C 进行编程,不是吗?;-)

在我看来,是的——我们这样做。如果仅出于一个原因 - 它们更容易掌握、理解,并且它们比函数更广泛地使用。

另外,-1,因为我认为这不是一个建设性的问题。如果您不喜欢它们,请不要使用它们。

于 2010-10-15T15:09:19.813 回答
0

如果我理解正确的话,Stefano 并不反对子程序的想法。反对他们的意见是无稽之谈。他反对对子程序/函数使用不同的风格。

Fortran 是命令式编程语言。更准确地说,它是一种过程编程语言(更准确地说,它是结构化编程语言)。

在命令式编程中,我们有一个状态和语句来改变它。在过程编程中,我们进行更改的工具是过程(我们在过程中本地化更改)。该过程可能会或可能不会返回一些值。而且我不认为这个事实(过程返回值与否)是在编程语言中有两个不同实体的重要原因。我们可以只有函数(就像在 C 中一样),并且当我们实际上不需要返回某些东西(void)时只返回一些特殊的东西。或者我们可以只使用允许返回值的过程和特殊语法,例如 Modula-2、Oberon、...

该语言可能应该只有一种风格来声明过程。我同意你的看法,斯特凡诺。

于 2010-10-15T12:58:13.220 回答
-3

我必须回答自己这个问题的事实是疯狂的,但事实就是如此。

不同之处在于您不能在 Fortran 中“像其他语言一样调用函数”。在 C 中,您可以在不分配值的情况下调用整数函数,例如

int foo() {
    return 5;
}
int main() {
    foo(); // this works
}

在 Fortran 中,您总是必须关联一个接收变量。例子

module test
   implicit none

contains
   integer function foo()
      print *, "hello"
      foo = 0
   end function

end module

program hello
   use test
   integer :: x

   x = foo() ! this works
   foo() ! this does not compile

end program hello

这意味着通过返回一个虚拟整数来“模拟”一个 void 函数仍然不允许您在没有接收器变量的情况下调用。

在 Fortran 中,void返回类型不存在。从技术上讲,你可以用所有函数来构建你的程序,用上面看到的替换call语句的每个出现x =,但这不会使你的语法类似于 C 或其他语言,其中没有返回 void 的函数和非无效返回函数。子例程是唯一允许“返回 void”的实体,但执行调用的语义完全不同。除此之外,两者没有区别。

于 2010-10-15T14:48:54.597 回答