【发布时间】:2020-04-28 23:36:47
【问题描述】:
我正在尝试弄清楚移动语义如何影响引用透明度。
Referential transparency (RT) 允许我们用它的结果替换任何表达式而不改变程序的含义(从Functional Programming in Scala 转述)。例如,我可以将程序中的任何地方的1 + 1 替换为2,并且什么都不会改变。这个 Python 程序是引用透明的:
@dataclass
class Bucket:
things: List[str]
leaves = ["leaves"]
def bucket_with_sand(things: List[str]) -> Bucket:
return Bucket(things + ["sand"])
bucket_with_sand(leaves) # can be replaced with Bucket(["leaves", "sand"]) with no change to the program
而这个函数改变了它的参数
def bucket_with_sand(things: List[str]) -> Bucket:
things += ["sand"]
return Bucket(things)
所以用结果替换函数调用会改变含义。它不再是引用透明的。在带有move semantics like Rust's 的语言中,我们可以通过移动leaves 来避免这个问题(并依赖于Vec 不是Copy 的事实):
struct Bucket {
things: Vec<&str>,
}
let leaves = vec!["leaves"];
fn bucket_with_sand(things: Vec<&str>) -> Bucket {
things.push("sand");
Bucket { things }
}
bucket_with_sand(leaves); // mutates `things`
// doesn't matter that `leaves` has been mutated here as it's now out of scope
这似乎又是引用透明的。它是否正确?这些举措是否放松了对 RT 设计的传统限制?还是移动不是参照透明的?我特别想知道是否对 RT 有更广泛的影响,但我还没有看到。
【问题讨论】:
-
好吧,你的函数内部发生了变异,但如果你只谈论你的函数可能产生的副作用,是的,让所有权让它在她之外没有副作用。 (但不要忘记 Rust != haskell,不要仅仅为此提供向量的所有权,这不是 Rust 的方式)
-
@Stargateur 您能否详细说明“这不是 Rust 的方式”。为什么不是这样?
-
特别是,它似乎是一条非常简洁的 FP 途径,而无需“处理”副作用
-
我觉得和纯函数的概念有关
标签: functional-programming rust move-semantics referential-transparency