在.net中,變數的存放可以放在兩個地方堆疊(stack)和堆(heap)中,放在堆疊的變數型別被稱為值型別,而放在堆中的被稱作為引用型別。值型別就是在堆疊中擁有固定大小的空間,比如int、float型別,引用型別,在堆疊上僅僅儲存乙個指標,指向堆中內容的位址。儘管雖然指標具有固定的大小,比如4個位元組或者8個位元組,但是它指向堆中存放的內容可以是更大的。
在f#中,變數的存放機制跟.net的其它語言是一樣的,對於基本型別的值都是存放於堆疊中(string型別除外),其它的比如list、array和type型別都是存放於堆中。然後,由於f#是一種函式式程式語言,它的值一經定義,是不能改變的。要改變值,只能把值申明為改變型別(mutable)或者是引用型別(ref)。
一、mutable
mutable關鍵字用於定義值的前面,表示這個值是可變的,改變乙個可變值,不是像c#一樣,使用"=",而是使用"<-",比如:
> let mutable message = "world";;
val mutable message : string = "world"
> printfn "hello, %s" message;;
hello, world
val it : unit = ()
> message <- "universe";;
val it : unit = ()
> printfn "hello, %s" message;;
hello, universe
val it : unit = ()
在這裡,對於可變值的使用,還是有一些的限制。這主要是clr處於安全方面的考慮,這樣可以防止編寫**的時候使用隨處使用可變值,在f#中,使用可變值的限制有:
1、可變值不能從函式中返回
2、可變值不能被內嵌函式使用
比如,下面的示例,在函式invaliduseofmutable()中定義了乙個可變值x和乙個內嵌函式incrementx(),x在函式incrementx()中使用將是非法的,將會導致異常:
> let invaliduseofmutable() =
- let mutable x = 0
- let incrementx() = x <- x + 1
- incrementx()
- x;;
let incrementx() = x <- x + 1
-----------------------^^^^^^^^^^^
stdin(16,24): error fs0407: the mutable variable 'x' is used in an invalid way.
mutable variables may not be captured by closures. consider eliminating this use
of mutation or using a heap-allocated mutable reference cell via 'ref' and '!'.
二、reference
為了解決能把申明的可變值用於內嵌的函式中,可以利用ref關鍵字把可變值的存放方式由堆疊改為堆。ref關鍵字的作用就是允許把可變值存放於堆中,是你可以繞過在堆疊中使用可變值的限制。為了獲取ref型別的值,可以使用操作符!,同時利用操作符:=來設定ref型別的值,ref關鍵之不僅僅可用於乙個型別中,還可以用在函式,就像c#的方法返回乙個引用一樣,它僅僅返回的是函式的副本。下面的兩個示例分別說明了利用ref把值型別存放在堆中以及返回乙個函式的引用。
1)改變值型別的存放
> let x = ref 0;;
val x : int ref =
> !x;;
val it : int = 0
> x := 1;;
val it : unit = ()
> !x;;
val it : int = 1
2)返回函式的副本
> let funccopy = ref (fun x y -> x + y);;
val funccopy : (int -> int -> int) ref =
> !funccopy 1 2;;
val it : int = 3
三、mutable records
可變性不僅僅能用於改變單一的值,記錄中的字段也可以標識為可變,這就允許你在命令式程式設計風格中使用記錄了。為了標記乙個欄位為可變,只需要簡單的在字段前面使用mutable關鍵字,比如下面的示例:
> open system
- type mutablecar =
val driveforaseason : mutablecar -> unit
> let kitt =
- driveforaseason kitt
- driveforaseason kitt;;
val kitt : mutablecar =
F 程式設計 函式式程式設計之Records
當你想把資料組成乙個結構化的格式,而不需要太複雜的語法時,你可以使用f 中的record型別。record型別與c語言的struct型別基本一樣,儲存一組型別的值,通過欄位的值來獲取。定義乙個record型別很簡單,只需要在大括號內定義系列的名稱 型別就可以。要例項化乙個record,只需要提供對應...
Rust常用程式設計概念之變數和可變性
time 20190921 rust的學習曲線相對陡峭,更好的學習方式是先把概念理清楚,形成相對巨集觀的認知後,再動手實踐,和一般的語言學習方式略有不同。具體說就是,會涉及到rust語言的以下概念 預設情況下,變數是不可變的,如果想讓變數顯式可變,則用mut關鍵字修飾即可。那我們一定想問,這麼設計的...
F 函式式程式設計之 面向鐵道程式設計
原文 參考 不長,先看 吧,我在 後面寫講解。type request let validatename request match request with when name error name must not be blank ok request let validateemail fu...