gle*_*nsl 4 arrays string syntax ocaml
为什么数组和字符串索引使用微妙的不同语法?
例如
let _: int = [|1;2;3|].(0)
let _: char = "123".[0]
Run Code Online (Sandbox Code Playgroud)
我(和其他人)发现这既奇怪又令人困惑.
出于与Ocaml +用于整数加法和+.浮点数添加的完全相同的原因:OCaml放弃ad-hoc多态/函数重载和索引运算符当前被认为是OCaml中的一种函数形式,因此受到与函数相同的限制.
更准确地说,索引运营商目前正在一个很浅的语法糖:解析器重写x.(n)到Array.get x n和x.(n) <- y到Array.set x n y(或Array.unsafe_get并Array.unsafe_set在编译时-unsafe的选项).同样,
s.[n]被重写String.get s n并s.[n]<-x成为String.set s n x.
这意味着可以通过定义新Array模块来定义自己的索引运算符.例如,以下不明智的技巧将使数组索引从以下开始1:
module Array = struct
include Array
let get a n = get a (n-1)
let unsafe_get a n
end
;; [|1|].(1)
Run Code Online (Sandbox Code Playgroud)
请注意,无法保证这种hackish代码将来会起作用.如果要定义自己的索引操作符,就可以开始OCaml的≥4.06由点之间插入至少一个(运营商)字符定义扩展索引操作符.和左括号(或者(,[,{).
let (.?()) dict key = Dict.find_opt dict key
Run Code Online (Sandbox Code Playgroud)
如果你以某种方式希望减少索引操作符,那么就有一个命题可以使类似数组的数据类型的索引成为基本操作,而不是函数调用.这将允许使用类型导向的消歧,就像它已经为记录字段所做的那样.这意味着两者
let first (s:string) = s.(0)
let first (a: _ array) = a.(0)
Run Code Online (Sandbox Code Playgroud)
因为类型检查器将使用类型信息来解析应该使用哪个基元操作,所以是可能的.
但是,此提议仍在进行中(请参阅https://github.com/ocaml/ocaml/pull/616),因此现在需要通过语法区分字符串和通用数组索引.