我们还需要子程序吗?

时间:2010-10-15 11:21:45

标签: fortran fortran95

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

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

我错了吗?由于子程序具有的功能和功能没有,我们是否还需要Fortran编程中的子程序?

5 个答案:

答案 0 :(得分:17)

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

例如,编译器可以优化

x = foo(args)+ foo(args)

x = 2 * foo(args)

或者另一个例子,考虑

x = y + foo(y)

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

一般来说,几位专家的建议是只有在纯函数时才使用函数,否则使用子程序。而且,这也是我跟随自己的建议。

答案 1 :(得分:5)

我认为子程序无处可去。大多数其他语言允许使用和不返回值的方法。我看不出有什么理由说这是件坏事。不应该动摇任何人改变一件事。

只有Legacy表示,只要Fortran有效,子程序就会持续存在。只要Fortran存在,编写执行操作并且不返回任何内容的方法就没有错。

更新:

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

自从版本77以及可能更早版本以来,Fortran一直在区分函数和子例程。其他C系列语言也可以。为什么这突然间这么麻烦?即使长时间使用指针和对象的语言也有返回void的方法。

答案 2 :(得分:2)

你想再次在Fortran中编程C,不是吗? ; - )

在我看来,是的 - 我们这样做。因为只有一个原因 - 它们更容易掌握,理解,并且它们比功能更广泛地使用。

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

答案 3 :(得分:0)

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

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

在命令式编程中,我们有一个状态和语句来改变它。在程序编程中,我们要做更改的工具是程序(我们在程序中本地化变更)。该程序可能会或可能不会返回某些值。而且我不认为这个事实(无论是程序返回值还是没有)都是在编程语言中拥有2个不同实体的重要原因。我们只能有函数(比如C语言),当我们实际上不需要返回某些东西(void)时,只返回一些特殊的函数。或者我们只能使用过程和特殊语法来返回像Modula-2,Oberon那样的值......

语言可能只有一种样式来声明程序。我同意你,斯特凡诺。

答案 4 :(得分:-2)

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

差异源于你无法在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-returns函数和非void返回函数之间没有区别。子例程是唯一允许“返回void”的实体,但执行调用的语义却完全不同。除此之外,两者之间没有区别。