0

I'm interested in how List.init and other library functions are implemented in OCaml. Where can I see the implementations? I checked this official link: https://v2.ocaml.org/api/List.html and only found the function signatures.

3 Answers 3

2

OCaml, including its standard library, is entirely open source and at time of writing hosted on GitHub here: https://github.com/ocaml/ocaml/

The List.init function (located here) is split across a couple utility functions and actually has two different implementations with different performance characteristics that is selected based on a stack size heuristic and the length of the requested list:

let rec init_tailrec_aux acc i n f =
  if i >= n then acc
  else init_tailrec_aux (f i :: acc) (i+1) n f

let rec init_aux i n f =
  if i >= n then []
  else
    let r = f i in
    r :: init_aux (i+1) n f

let rev_init_threshold =
  match Sys.backend_type with
  | Sys.Native | Sys.Bytecode -> 10_000
  (* We don't know the size of the stack, better be safe and assume it's
     small. *)
  | Sys.Other _ -> 50

let init len f =
  if len < 0 then invalid_arg "List.init" else
  if len > rev_init_threshold then rev (init_tailrec_aux [] 0 len f)
  else init_aux 0 len f
Sign up to request clarification or add additional context in comments.

3 Comments

Now I'm curious: why is init_aux preferable over init_tailrec_aux (if there's enough stack space for it)?
It should be faster since it allocates half as much. The tail recursive implementation also has to reverse the list after it's constructed. See also this discussion on the performance of various implementations of List.map: discuss.ocaml.org/t/…
Oh now I feel dumb, I didn't spot the rev call which of course is necessary… I'm accustomed to putting the rev in the base case of the tail recursion where it would've been clearer.
2

If you have an OCaml source release, you can find the standard library implementation in the stdlib directory. The list implementation is stdlib/list.ml.

Here is List.init:

let rec init_tailrec_aux acc i n f =
  if i >= n then acc
  else init_tailrec_aux (f i :: acc) (i+1) n f

let rec init_aux i n f =
  if i >= n then []
  else
    let r = f i in
    r :: init_aux (i+1) n f

let rev_init_threshold =
  match Sys.backend_type with
  | Sys.Native | Sys.Bytecode -> 10_000
  (* We don't know the size of the stack, better be safe and assume it's
     small. *)
  | Sys.Other _ -> 50

let init len f =
  if len < 0 then invalid_arg "List.init" else
  if len > rev_init_threshold then rev (init_tailrec_aux [] 0 len f)
  else init_aux 0 len f

You can find recent OCaml releases on github. Here is a link to the latest release at the present time (I believe): OCaml 4.14.0 source tgz

Comments

0

You can always read the implementation in the sources: https://github.com/ocaml/ocaml/blob/trunk/stdlib/list.ml

1 Comment

Links can break. Answers that link to source like this might be improved by including manageable chunks of code directly in the answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.