我试图弄清楚移动语义如何影响引用透明度。
引用透明性(RT) 允许我们用其结果替换任何表达式,而不会改变程序的含义(从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)
因此用结果替换函数调用会改变含义。它不再是引用透明的。在像 Rust 那样具有移动语义的语言中,我们可以通过移动(并依赖于非-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 有更广泛的影响,而我还没有看到。