移动语义对于 Rust 中的引用透明性意味着什么?

2024-04-14

我正在尝试弄清楚移动语义如何影响引用透明度。

参考透明度 https://stackoverflow.com/q/210835/5986907(RT) 允许我们用结果替换任何表达式,而不改变程序的含义(释义自)。例如,我可以替换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 一样移动语义 https://stackoverflow.com/q/30288782/5986907,我们可以通过移动来避免这个问题leaves(并且基于这样的事实Vec is non-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 也不例外。调用可能会产生副作用——从执行 IO 到内存不足,再到仅仅改变可变变量——并且根据您是否在“没有任何改变”的意义上包含这些内容,您可能会认为函数是非函数。参照透明。它们不是纯粹的数学函数,而是在调用时确实会改变世界状态的过程。

也就是说:Rust 所谓的“所有权”系统——它的“仿射”或“移动”类型与其多读者/单作者借用系统的组合——可以大大减少在一个程序。特别是它(大部分*)消除了大多数其他命令式语言中最普遍和最有害的副作用:可变别名。也就是说,在 Rust 中,你(大多数*)永远不会对同一内存位置有两个或多个引用,其中一个函数中的一个引用会改变内存位置,作为运行的副作用,而其他函数中的另一个引用只会看到内存位置中的值“突然改变”。这意味着任何时候一个值要发生变异时,它都会通过它的唯一电流参考-- 要么&mut或拥有变量——这意味着,正如您在这里所问的,一定程度关于引用透明性的假设在 Rust 中比在大多数其他命令式语言中更有可能成立。

上面的“(mostly*)”星号指出了另一个相对较大的例外:不安全代码可能违反此规则,并且在多个库函数中都是如此。例如Rust 标准库的一部分 https://doc.rust-lang.org/reference/interior-mutability.html提供了所谓的“内部可变性”不安全的细胞类型 https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html以及强制禁止可变别名的包装类型动态地,以一种时间方式:可能会发生这样的可变访问在给定的时间但允许它们按顺序从不同的共享引用中顺序发生。

同样的警告适用于几乎所有真正的语言,无论它的营销本身多么“纯粹”:ML 系列有ref细胞,Haskell 有它的不安全的库函数 https://wiki.haskell.org/Unsafe_functions, Lisp 有set!等等。这些都是对以下事实的让步:有时,能够通过数学抽象(函数语言中的纯值,或 Rust 中的仿射值)通过其不受限制的可变别名到达底层机器,会带来压倒性的性能优势。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

移动语义对于 Rust 中的引用透明性意味着什么? 的相关文章

随机推荐