F 程式設計 函式式程式設計之值的可變性

2021-05-17 16:00:11 字數 2460 閱讀 6469

在.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...