第 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|]

以统一处理这两种情况。