我是函数语言的新手,我想知道为什么我们不能通过引用传递参数。 我发现有人说
创建对象后,您不应更改其状态
但我不太明白。
答案 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 ++之类的语言,其中实现细节会影响可变性,而不是现代语言的实际实现细节,在现代语言中,引用通常是在幕后传递的,但是通过其他方式可以确保不变性。)