字符串和数组索引的语法区别

4
为什么数组和字符串索引使用略有不同的语法?
例如:
let _: int  = [|1;2;3|].(0)
let _: char = "123".[0]

我(以及其他人)认为这很奇怪和令人困惑。
1个回答

10
出于与Ocaml使用+进行整数加法和+.进行浮点加法完全相同的原因:OCaml放弃了特设多态/函数重载,而索引运算符目前被视为OCaml中的一种函数形式,因此受到与函数相同的限制。
更准确地说,索引运算符目前是一种非常浅的语法糖:解析器将x.(n)重写为Array.get x n,将x.(n) <- y重写为Array.set x n y(如果使用-unsafe选项编译,则为Array.unsafe_getArray.unsafe_set)。同样,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)

请注意,这种hackish代码未来可能无法正常工作。如果您想定义自己的索引运算符,可以从OCaml≥4.06开始通过在点 . 和左括号( [ { )之间插入至少一个(操作符)字符来定义扩展的索引运算符。
let (.?()) dict key = Dict.find_opt dict key 

如果你希望减少索引运算符的使用,有一个提议是将数组类型的索引操作作为原始操作而不是函数调用。这将允许使用类型导向消歧,就像记录字段已经做的那样。这意味着两者都可以...
 let first (s:string) = s.(0)
 let first (a: _ array) = a.(0)

由于类型检查器将使用类型信息来解析应使用哪个原始操作,因此可能是可行的。
但是,这项提议仍在进行中(请参见https://github.com/ocaml/ocaml/pull/616),因此现在需要通过语法区分字符串和通用数组索引。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接