过程式语言和函数式语言之间的区别?

Ent*_*ing 1 c procedural haskell functional-programming

我最近在一次采访中被问到这个问题。我无法得到正确的答案。

当您使用相同的参数重复调用过程语言(如 C)和函数语言(如 haskell)中的函数时,您可能会得到不同的结果?我在[this](过程式编程和函数式编程之间有什么区别?)帖子中读到,纯函数式语言总是会产生相同的答案。为什么函数式语言会出现这种情况,而过程式语言则不然?

chi*_*chi 5

在命令式编程中,函数被允许有副作用,比如修改变量的值、写入文件、访问网络等。第二次运行同一个函数时,它可以检测到之前的副作用并返回一些东西不同的。一个简单的 C 示例是:

int i = 0;
int foo() {
  return i++;
}
Run Code Online (Sandbox Code Playgroud)

多次调用会生成不同的数字。另一个例子:

int foo(int *p) {
  return (*p)++;
}
Run Code Online (Sandbox Code Playgroud)

即使使用相同的参数(即相同的指针)调用上面的方法,结果也会因为增量而不同。

i++函数式编程中,设计上禁止出现诸如此类的副作用。这样,函数的输出必须仅取决于其参数的值。例如,如果在 Haskell 中我们有一个f类型为 的函数Int -> Int,我们可以确定f 3每次调用都会返回相同的整数。

嗯,上面的说法并不完全正确——程序最终必须执行一些 I/O,否则就没有意义。因此,副作用必须以某种形式存在。在 Haskell 中,实际上允许有副作用的函数,但它们的类型必须告诉它们不是纯函数。例如,如果函数g具有 type Int -> IO Int,那么它可以执行 I/O 并具有副作用:print =<< g 3每次运行都可以打印不同的值,就像在命令式编程中一样。

因此,总而言之,在纯函数式编程中,具有副作用的函数与没有副作用的函数具有不同的类型。通常,在设计良好的函数式程序中,很少需要 I/O 和副作用,纯函数构成了绝大多数代码。正因为如此,有时我们会说“纯函数式编程禁止副作用”,因为大多数代码都是在这种约束下编写的。