What does `#use "topfind"` do and why do I need it?

I’ve seen this in a few places. When I was setting up down for my ocaml shell I added that to my ~/.ocamlinit to make things “work”.

But what is it?

It is necessary to be able to use ocamlfind from inside the toplevel.

When you install the ocamlfind package, it installs a file called topfind in the standard library directory. Inside this file there are commands to load the Findlib library which in turn registers (using compiler-libs hooks) the #require directive and other related Findlib features, and prints a short help text when it is done.

Cheers,
Nicolas

1 Like

To add only a tiny bit to @nojb 's to-the-point explanation: one might ask why this is necessary: why, after all, doesn’t OCaml come with a standard package-manager that’s built-into the toplevel (and compiler/linker). And the answer I like, is that OCaml doesn’t make those sorts of assumptions, and this is a good thing, b/c somebody might come along with something better than findlib/ocamlfind/#require, and if OCaml had chosen one package-manager, then it’d be tough for that newcomer to do something different.

And even so, if one finds having to type that text #use "topfind";; onerous, one can always put it in one’s ~/.ocamlinit file.

Lastly, I maintain camlp5. And camlp5 wants to add a few lines to topfind – a few extra commands, basically. And it’s great that doing so is really simple.

1 Like

I use utop as my REPL and I’ve never needed that. #require "..." works for me directly.

Yes I’d previously used utop without needing it (I guess utop does it implicitly?)

I really like the more minimal prompt and better tab completion UI from ocaml+down at the moment though.

Anyway I just wondered what it was, and “provides the #require directive” answers it well.

I’ve quite happily added it to my ~/.ocamlinit and can forget about it (I assume there’s no downside?)

Note though that the tab completion of down is orders of magnitude dumber than utop’s one: it does not consider scopes/open. See this issue.

This is a misconception, this is not about package managing, this is about being able to load a compiled object and its dependencies in the toplevel.

You can try to convince me as much as you want that having no support for this is actually a great idea, there’s only one way in which I can see that: defective (and btw. why do it for C dependencies an not OCaml ones…)

3 Likes

There’s a second way: preprocessors. Camlp5’s preprocessing method is not achievable in the PPX design.

Another way that package-managers differ from just “find the library to link” is that (for instance with ppx_deriving) you can have a bunch of plugins (viz. show, eq, ord, etc) and then you can have meta-packages like std that pull a number of the named ones in.

If you really have to, then fake, nop dependencies are easy to introduce between modules:

 let () = Sys.opaque_identity (fun () -> let module D = Yourdep in ()) ()

Alternatively that seem easy to control via simple include directories.

In fact since that other discussion made me look again into it, that was the model I was using in b0caml: directories with modules therein (and the actual linking business done in a data-driven like manner like omod does).