當我在F#中創建一個包含F#中的泛型,可變.NET堆棧的類時,該堆棧忽略了我所推送的任何東西。F#中member val和member之間的區別是什麼?
open System.Collections.Generic
type Interp(code: int array) =
member val PC = 0 with get, set
member this.stack: Stack<int> = new Stack<int>()
member this.Code = code
let interp = Interp([|1;2;3|])
interp.stack.Push(1)
printfn "%A" interp.stack // prints "seq[]" WAT?!
然而,如果我做堆棧可變通過屬性:
open System.Collections.Generic
type Interp(code: int array) =
member val PC = 0 with get, set
member val stack: Stack<int> = new Stack<int>() with get, set
member this.Code = code
let interp = Interp([|1;2;3|])
interp.stack.Push(1)
printfn "%A" interp.stack // prints "seq[1]"
一切神奇就像我所期待。
這到底是怎麼回事?我對先前語言(主要是C#)的不變性的理解會說,即使第一個例子中的堆棧是不可變的成員,但這個不可變性只應該引用到參考(也就是說我不應該重新分配堆棧本身)。我仍然應該能夠向它推送值。我錯過了什麼,如果試圖改變堆棧是錯誤的,爲什麼不拋出異常或編譯錯誤?
關於'member val Stack = new Stack(),get,set',什麼是不成語? –
Daniel
@Daniel爲不會變異的成員創建一個可變字段不是慣用的。 – phoog
@Daniel或更多點,通常更喜歡不可變類型,或者至少會員,而不是可變類型。 – phoog