Stumbling upon this other thread, I realized that OCaml has support for immutable arrays:
And indeed, those are part of OCaml 5.4: module Iarray and also a type iarray (for which I don’t seem to find an entry in the manual here; maybe it is missing in the manual?).
It doesn’t have an indexing operator (#13784), but you can define one.
I struggle a bit when and how to use that new type. In my case, I have written a solver for linear equation systems using the Gauss method. I would like the types to be something like:
val solve : (Num.t iarray * Num.t) list -> Num.t array option
with some generic number module Num.
I don’t want the function to modify/destroy the input arguments. So I assume changing my function to accept an iarray is fine? But while I’m calculating the output, as a last step of the Gauss algorithm, I keep the numbers in a mutable array anyway. So is it reasonable to return that mutable array instead of converting it into an immutable array? (Afterall, some future users of my function might want to modify the result.)
Or should I stick to one kind of array and use it consistently for input and output?
What are other people’s experiences with using iarray? I noticed that refactoring my code to use iarray instead of array is quite a lot of work, especially as I will have to do that replacement in some places, while in others I need to keep mutability. So I would need to duplicate some code, e.g. here in my tests (using Alcotest):
(** Tests rational numbers ([Q.t]). *)
let testable_q : Q.t Alcotest.testable = Alcotest.testable Q.pp_print Q.equal
(** Tests rational vectors (i.e. arrays of rational numbers). *)
let testable_qvec = Alcotest.array testable_q
+
+(** Tests immutable rational vectors. *)
+let testable_qivec =
+ Alcotest.testable
+ (fun f x -> Format.pp_print_array Q.pp_print f (Iarray.to_array x))
+ (Iarray.for_all2 Q.equal)
Also note that there doesn’t seem to be an Alcotest.iarray, so I have to convert my iarray first to an array before Alcotest is able to process it. Either by providing a corresponding testable as above, or by manually converting all iarrays into array before letting Alcotest process them.
Is this friction going to be better within time (possibly leading to more duplication in libraries?), or is iarray more to be seen as a special type that you only use when you really need it, and otherwise stick to array and/or making types abstract when you want to avoid access from outside?