为什么纯函数式语言只允许按值传递参数?

时间:2018-07-11 10:20:00

标签: reference functional-programming parameter-passing purely-functional

我是函数语言的新手,我想知道为什么我们不能通过引用传递参数。 我发现有人说

  

创建对象后,您不应更改其状态

但我不太明白。

3 个答案:

答案 0 :(得分:1)

我认为您对这个概念有误解。 Scheme和C / C ++都是按值传递语言,并且大多数值都是地址(引用)。

纯函数式语言可以具有引用,并且引用是按值传递的。他们没有的是在同一范围内重新定义变量(突变绑定),并且他们没有可能更新参考指向的对象。所有操作都返回一个新的新对象。

作为一个例子,我可以给你Java的字符串。 Java不是纯粹的功能,而是它的字符串。如果将字符串更改为大写,则会返回一个新的字符串对象,并且原始对象未更改。

我所知道的大多数语言都是按价值传递的。传递名字对我来说是陌生的。

答案 1 :(得分:1)

您可以不能传递引用,不是很多,而是在引用透明的情况下,引用和值之间没有程序员可见的区别,因为不允许您更改内容参考指向。这实际上使得在纯函数式编程中更安全,更普遍地在任何地方传递共享引用。从语义的角度来看,它们也可能是值。

答案 2 :(得分:-1)

因为如果通过引用传递参数,则可以更改参数中的某些内容,这可能会带来副作用。考虑一下:

function pay(person, cost) {
  person.wallet -= cost;
}

function money(person) {
  return person.wallet;
}

let joe = { name: "Joe", wallet: 300 };
console.log(money(joe));   // 300
pay(joe, 20);
console.log(money(joe));   // 280

两个money(joe)接受相同的输入(对象joe)并提供不同的输出(300、280)。这与纯函数语言的定义是矛盾的(当给定相同的输入时,所有函数都必须返回相同的输出)。

如果程序是这样制作的,那就没问题了

    function pay(person, cost) {
      return Object.freeze({ ...person, wallet: person.wallet - cost });
    }

    function money(person) {
      return person.wallet;
    }

    let joe = Object.freeze({ name: "Joe", wallet: 300 });
    console.log(money(joe));                 // 300
    let joe_with_less_money = pay(joe, 20);
    console.log(money(joe));                 // still 300
    console.log(money(joe_with_less_money)); // 280

在这里,我们必须通过冻结对象来伪造值传递(这使它们不可变),因为JavaScript只能以一种方式传递参数(通过共享传递),但是思想是相同的。

(这预先假定了“按引用传递”一词的含义,适用于C ++之类的语言,其中实现细节会影响可变性,而不是现代语言的实际实现细节,在现代语言中,引用通常是在幕后传递的,但是通过其他方式可以确保不变性。)