Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

syntax for string vs array indexing

Why is it that array and string indexing uses subtly different syntax?

E.g.

let _: int  = [|1;2;3|].(0)
let _: char = "123".[0]

I (and others) find this to be both weird and confusing.

like image 974
glennsl Avatar asked Jan 04 '23 10:01

glennsl


1 Answers

For exactly the same reason that Ocaml use + for integer additions and +. for float additions: OCaml foregoes ad-hoc polymorphism/function overloading and indexing operators are currently considered as a form of functions in OCaml and are thus subject to the same restrictions as functions.

More precisely, indexing operators are currently a very shallow syntax sugar: the parser rewrites x.(n) to Array.get x n and x.(n) <- y to Array.set x n y (or Array.unsafe_get and Array.unsafe_set if compiled with the -unsafe option). Similarly, s.[n] is rewritten to String.get s n and s.[n]<-x becomes String.set s n x.

This means that it is possible to define your own indexing operator by defining a new Array module. For instance, the following ill-advised trick will make array indices start at 1:

 module Array = struct
   include Array
   let get a n = get a (n-1)
   let unsafe_get a n 
 end
 ;; [|1|].(1)

Note that there is no guarantee that this kind of hackish code will work in the future. If you want to define your own indexing operator, it is possible starting with OCaml ≥ 4.06 to define extended indexing operator by inserting at least one (operator) character between the dot . and the left bracket (either (, [, {).

let (.?()) dict key = Dict.find_opt dict key 

If you, somehow, wish for less indexing operators, there is a proposition to make indexing for array-like data types a primitive operation and not a function call. This would allow to use type-directed disambiguation like it is already done for record fields. This means that both

 let first (s:string) = s.(0)
 let first (a: _ array) = a.(0)

would be possible since the type-checker will use type information to resolve which primitive operation should be used.

However, this proposal is still a work in progress (see https://github.com/ocaml/ocaml/pull/616 ), so for now it is required to distinguish between string and generic array indexing by the syntax.

like image 69
octachron Avatar answered Jan 22 '23 20:01

octachron