簡體   English   中英

移動語義對於 Rust 中的引用透明性意味着什么?

[英]What do move semantics imply for referential transparency in Rust?

我正在嘗試弄清楚移動語義如何影響引用透明度。

引用透明(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 有更廣泛的影響,我還沒有看到。

在幾乎所有在真實計算機上執行的語言中,引用透明的概念都有些模糊,尤其是在具有命令式狀態的語言中,Rust 也不例外。 調用可能會產生副作用——從執行 IO 到內存不足,再到僅僅改變一個可變變量——根據你是否包括那些你認為“沒有變化”的函數,你可能會認為函數是非-參照透明。 它們不是純數學函數,而是在調用時確實會改變世界狀態的過程。

也就是說:Rust 所謂的“所有權”系統——它的“仿射”或“移動”類型與其多讀者/單作者借用系統的組合——用於顯着減少可能的副作用一個程序。 特別是它(主要是*)消除了大多數其他命令式語言中最普遍和最有害的副作用:可變別名 也就是說,在 Rust 中,您(大多數情況下*)永遠不會有兩個或多個對同一內存位置的引用,其中一個函數中的一個引用會改變內存位置作為運行的副作用,而另一個函數中的另一個引用只會看到內存位置中的值“突然改變”。 這意味着任何時候一個值要發生變異,它都會通過其唯一的當前引用發生變異——要么是&mut要么是一個擁有變量——這意味着,正如你在這里問的那樣,在某種程度上,關於引用的假設透明性在 Rust 中比在大多數其他命令式語言中更真實。

上面的“(mostly*)”星號說明了另一個相對較大的異常:不安全的代碼可能違反此規則,並且在幾個庫函數中也是如此。 例如,Rust 標准庫中提供所謂的“內部可變性”的部分提供了一種不安全的單元格類型以及包裝器類型,它們以時間方式動態地強制禁止可變別名:一個這樣的可變訪問可以發生在給定的時間,但允許它們從不同的共享引用依次發生。

同樣的警告適用於幾乎所有真正的語言,無論它推銷自己有多“純粹”:ML 系列有ref單元,Haskell 有不安全的庫函數,Lisps 已經set! 等等。 這些都是對這樣一個事實的讓步:有時能夠通過數學抽象(函數語言中的純值,或 Rust 中的仿射值)到達具有不受限制的可變別名的底層機器,具有壓倒性的性能優勢。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM