第 12 章 語言擴展

19 擴展索引運算符

(於 4.06 版本引入)

dot-ext::= 
 dot-operator-char { operator-char }
 
dot-operator-char::= ! ∣ ? ∣ core-operator-char ∣ % ∣ :
 
expr::= ...
 expr. [module-path.] dot-ext ( (expr) ∣ [expr] ∣ {expr} ) [ <-expr ]
 
operator-name::= ...
 .dot-ext (() ∣ [] ∣ {}) [<-]
 

此擴展為取得和設定使用者定義索引型別的元素提供了語法糖。例如,我們可以定義類似 Python 的字典,如下所示:

module Dict = struct include Hashtbl let ( .%{} ) tabl index = find tabl index let ( .%{}<- ) tabl index value = add tabl index value end let dict = let dict = Dict.create 10 in let () = dict.Dict.%{"one"} <- 1; let open Dict in dict.%{"two"} <- 2 in dict
# dict.Dict.%{"one"};;
- : int = 1
# let open Dict in dict.%{"two"};;
- : int = 2

19.1 多索引符號

expr::= ...
 expr. [module-path.] dot-ext(expr { ;expr }+) [ <-expr ]
 expr. [module-path.] dot-ext[expr { ;expr }+] [ <-expr ]
 expr. [module-path.] dot-ext{expr { ;expr }+} [ <-expr ]
 
operator-name::= ...
 .dot-ext ((;..) ∣ [;..] ∣ {;..}) [<-]
 

也透過第二種索引運算符變體支援多索引。

let (.%[;..]) = Bigarray.Genarray.get let (.%{;..}) = Bigarray.Genarray.get let (.%(;..)) = Bigarray.Genarray.get

當索引文字包含以分號分隔的兩個或多個元素的列表時,會呼叫此變體。

let sum x y = x.%[1;2;3] + y.%[1;2] (* 等同於 *) let sum x y = (.%[;..]) x [|1;2;3|] + (.%[;..]) y [|1;2|]

特別是,這種多索引符號使其能夠統一處理 Genarray 和多維陣列的其他實作的索引。

module A = Bigarray.Genarray let (.%{;..}) = A.get let (.%{;..}<- ) = A.set let (.%{ }) a k = A.get a [|k|] let (.%{ }<-) a k x = A.set a [|k|] x let syntax_compare vec mat t3 t4 = vec.%{0} = A.get vec [|0|] && mat.%{0;0} = A.get mat [|0;0|] && t3.%{0;0;0} = A.get t3 [|0;0;0|] && t4.%{0;0;0;0} = t4.{0,0,0,0}

請注意,多索引和單索引運算符之間的區別純粹是語法上的:多索引運算符僅限於包含一個或多個分號 ; 的索引表達式。例如:

let pair vec mat = vec.%{0}, mat.%{0;0}

等同於

let pair vec mat = (.%{ }) vec 0, (.%{;..}) mat [|0;0|]

請注意,在 vec 的情況下,我們正在呼叫單索引運算符 (.%{}),而不是多索引變體 (.{;..})。因此,多索引運算符的大多數用戶都需要聯合定義單索引變體,這一點是可以預期的。

let (.%{;..}) = A.get let (.%{ }) a k = A.get a [|k|]

以便統一處理這兩種情況。