8 2 3 1 可變狀態使用引用單元

2021-06-27 10:09:24 字數 1206 閱讀 8958

8.2.3.1 可變狀態使用引用單元

要回答這個問題,我們需要能夠建立一些要捕獲的狀態。乙個方法是用 let mutable,但是,這樣,並不能執行,因為這種可變值只能用於區域性,不能被閉包捕獲。

第二個方法是使用引用(ref)型別建立可變值,即引用單元(reference cell)的縮寫,它是能夠包含可變值的小物件(實際上,宣告為 f# 的記錄型別)。要理解引用型別的原理,我們在 c# 中定義同樣的型別,可以看到,相當簡單:

class ref 

public t value  

這裡最重要的是 value 屬性是可變的,所以,當我們建立了乙個不可變的 ref型別的變數時,仍然可以改變它代表的值。清單 8.8 是在 f# 中使用引用單元的例子,顯示了相當於 c# 使用ref型別的**;在 f# 中,不直接訪問型別,因為有乙個函式,也叫 ref,建立引用單元,以及設定和讀取值的兩個運算子。

清單 8.8 在 f# 和 c# 中使用引用單元

f# interactive

c#let st = ref 10

st := 11 

printfn "%d" (!st)

var st = new ref(10);

st.value = 11; 

console.writeline(st.value);

第一行,我們建立了乙個包含整數的引用單元,如同剛剛在 c# 中宣告的 ref型別一樣,f# 的 ref 型別是泛型的,所以,我們可以用它來儲存任何型別的值;接下來的兩行演示了使用引用單元的運算子:賦值(:=)和取消引用(!),f# 的運算子對應於設定和讀取屬性值,但語法更便利。

在 f# 4.0 中,對可變值的使用進行了簡化。

在 f# 中,雖然值預設是不可變的,但是,可變值也是是允許的。過去,關鍵字 mutable用於說明可變值使用棧,這種值使用 <- 運算子進行修改;如果可變值是由閉包捕獲的,那麼值就使用堆,需要使用ref 語法,愈發值是通過 := 運算子。

這些語法上的差異既使**不優雅,也讓開發人員困惑,很難弄清楚到底應該使用哪一種方法。

現在,使用 f# 4.0,開發人員只要用乙個關鍵字 mutable,就能搞定所有可變值,餘下的工作由編譯器完成:如果可能,就在棧上建立變,否則,隱式轉換成引用單元。

對於非常了解棧、堆語有錢人高階使用者,能夠啟用警告 3180(在 fsc.exe 或 fsi.exe 中,使用 --warnon:3180),當 mutable 宣告隱式轉換成 ref 時,會發出通知。

內部可變狀態escape例項

在高併發程式設計中,作者舉了乙個內部可變狀態escape的例子,不是很理解,自己又測試了一下,跟大家共享一下。class unsafestates public string getstates public class unsafestatestest 結果 akl理解重點 1.string的儲存...

Vue中Props 不可變狀態

所有的 prop 都使得其父子 prop 之間形成了乙個單向下行繫結 父級 prop 的更新會向下流動到子元件中,但是反過來則不行。這樣會防止從子元件意外改變父級元件的狀態,從而導致你的應用的資料流向難以理解。額外的,每次父級元件發生更新時,子元件中所有的 prop 都將會重新整理為最新的值。這意味...

可變引數使用

在c中,可變引數用於引數個數,型別不確定的情況,如printf,snprintf函式的實現。當我們無法列出傳遞函式的所有實參的型別和數目時,可以用省略號指定參數列 void func void func parm list,這是c傳參的一種形式,與固定引數不同。函式引數以棧的形式儲存,從右往左入棧。...