12.4.2 自定義 f# 語言
到目前為止,我們所討論過的序列表示式,都是用 seq 識別符號表示,後面的**塊括在大括號中。然而,f# 還允許我們建立自己的識別符號,給**塊以特殊的意義。通常,這個功能稱為計算表示式(computation expressions),而序列表示式是它的乙個特例,是由 f#核心所實現,並經編譯器優化。
我們已經知道,計算表示式可以包含標準的語言結構,比如 for 迴圈,還有別的結構,像 yield。在**塊之前的識別符號,描述構造的意義,其方式與查詢運算子(例如,select 和 where 擴充套件方法)描述 linq 查詢所執行的操作,完全相同。這就是說,我們可以建立自定義的計算表示式,用於處理選項值。我們可以用 for 結構處理選項值,但是,f# 提供了更好的自定義表示式的方法,在清單 12.16 中可以看到這些替代方法。第乙個版本使用的語法類似於序列表示式;第二個版本功能相同,但方法更自然。
清單 12.16 處理選項值的計算表示式 (f#)
// 使用自定義的 'for' 基本操作,進行值繫結
option {
for n in tryreadint() do
for m in tryreadint() do
yield n * m
// 使用專門的 'let!' 基本操作,進行值繫結
option {
let! n = tryreadint()
let! m = tryreadint()
return n * m
在計算表示式內部,所有自定義的基本操作(例如,for、yield 和 let!)所發生的行為,由可選(option)識別符號決定,它定義了我們所寫的計算表示式的種類。現在,我們可以知道,序列表示式就是由 seq 識別符號定義的特殊情況。我們將在 12.5 節學習定義識別符號,現在,先看一下清單 12.16 中的兩個例子。
第乙個版本與清單 12.15 中的 linq 查詢極為相似,每乙個 for 迴圈至少能夠執行一次。當選項值包含值時,將分別繫結到符號 n 或 m,並執行迴圈體。開發人員只希望迴圈處理集合,而是不處理選項值,而結構 for 和 yield 通常只能用於處理序列。當我們建立計算表示式,處理其他型別值時,將使用後面的語法。第二個版本使用了不止兩個計算表示式基本操作,第乙個是 let!,表示自定義的值繫結。
在這兩個版本中,值 n 和 m 的型別是整數,自定義的值繫結從型別 option的值中取出實際值。當從tryreadint 返回的值為 none時,它可能無法把值分配給符號,這樣,整個計算表示式將立即返回 none,不會執行其餘的**。表示式中的第二個非標準基本操作是 return,描述了如何從值構建選項值。在清單 12.16 中,我們給它的是整數值,它構造的結果型別是 option。
我們剛才所了解的概念,可以看作是一種函式式的設計模式,使用 f# 計算表示式,可以不要了解模式的所有細節。如果想學習如何自定義計算表示式,了解概念和術語有關的背景知識,是非常有用的。補充材料「計算表示式和單子」更詳細地討論了這種模式,以及它與 haskell 單子的關係。
計算表示式和單子
我們在前面提到過,f# 中的計算表示式是一種稱為單子(monads,一元運算)思想的實現,在 haskell 中非常有用。單子是數學術語,但 f# 使用了不同的名字,更好地反映了這種思想在 f# 語言中的使用。
當定義計算表示式(或單子)時,我們總是使用泛型型別,比如 m <'a>,這通常稱為單子型別(monadic type),它描述了計算的含義,這種型別能夠給我們所寫**增加了含義。例如,剛才我們看到的 option<'a>,給**增加了返回未定義值(none)的可能性。序列也是一種形式的單子,型別 seq <'a> 給**增加了處理多個值的能力。
每個計算表示式(或單子)是由兩個函式,bind 和 return,實現的。bind 能夠建立和組合計算,處理單子型別的值。在清單 12.16 中,每當我們使用 let! 基本操作時,就使用了bind 操作。return 用於構造單子型別的值。
值得注意的是,序列表示式也是單的乙個例項。對於序列,繫結操作是 seq.collect,雖然在序列表示式中,我們沒有用 let! 語法,而是使用更舒服的 for 迴圈語法。清單 12.16 展示了兩者密切相關。序列的 return 操作建立了只有乙個元素的序列。在序列表示式的內部,可以用更自然的 yield 基本操作來寫。
在下一節,我們將學習可能是最簡單的自定義計算,用 c# 和 f# 來實現,解釋單子型別的含義,以及 bind 和 return 操作。
c語言 自定義型別
struct stu 分號不能丟 匿名結構體型別 struct x struct a 20 p p x 非法的操作,上面倆種完全是不同的宣告 struct node 結構體的自引用 struct node n1 null 直接初始化 struct node n2 null 結構體巢狀初始化 先來看下...
C語言 自定義函式
c語言 關於自定義函式 return type function name datetype arg datetype arg2 函式三要素 函式返回值 函式名 引數列表 例子呀 自定義函式的完整寫法 include 函式原型 int sum int,int 可以只寫型別,引數名稱可省略 int m...
C語言自定義型別
在學習c語言的時候,它有很多的自定義型別,例如 結構體,列舉,聯合。這些型別在我們的日常使用的時候,或多或少的都會遇見到,下面就系統的介紹一下這幾種型別。一.結構體 1.結構體型別的宣告 通俗點來說,結構就是一些值的集合,這些值稱為成員變數,結構體的每個成員可以是不同型別的成員變數。如下所示 str...