Search code examples
ocamlutop

Embed top-level directive in ml files


I might be thinking about the top-level the wrong way. What is the preferred way to maintain a collection of top-level directives as part of a project?

Is there a way to include top-level directives like #install_printer in an OCaml source file so that they are ignored when the program is compiled but executed by the top-level when running?

Ideally, I'd also like the directives to be type checked when the program is compiled even if the directive itself is ignored, e.g.

type 'a with_infinity = Finite of 'a | Infinite

let print_int_with_infinity pp item =
(match item with
    | Infinite -> Format.pp_print_string pp "Infinite"
    | Finite i -> Format.pp_print_int pp i)

(* install printer cannot occur in this context *)
#install_printer print_int_with_infinity

Solution

  • A good way to work with the toplevel is to have a .ocamlinit file at the root of the project. This file is loaded when you launch utop or ocaml from the same directory.

    It typically looks like this:

    #use "topfind";;
    #require "this";;
    #require "that";;
    
    let _printer = ...;;
    #install_printer _printer;;
    ...
    

    On a related note, if the environment variable OCAMLPATH is set to /path/to/my/project:..., and there's a proper META file in /path/to/my/project/foo, it is then possible to load the project-local foo library and its dependencies using #require "foo".