use packages installed with opam inside utop - ocaml

I installed yojson with opam:
opam install yojson
and I want to use it inside utop, but I haven't been able to make it work. I've tried these commands inside utop and none of them worked (it complains that it can't find the file / package):
#use "Yojson";;
#use "yojson";;
#require "Yojson";;
#require "yojson";;
Is there any additional configuration I should be aware of to use opam packages in utop?

The correct invocation is (include the # character):
#use "topfind";;
#require "yojson";;
The first command enables the #require directive (it is not the standard one, but comes from the ocamlfind tool), it is a good idea to add it to your ~/.ocamlinit file, if it is not there already. The second directive, actually loads the yojson library. You can also use the #list directive to list all available packages, as well as the ocamlfind list shell command for the same puprose.

Related

Syntax error when using batteries in Utop

I've successfully installed Batteries and can get it work...somewhat.
Any ideas why I'm getting the syntax error since Opam list this:
depends: "ocaml" {>= "4.00.0" & < "4.10.0"}
And, I'm at: The OCaml toplevel, version 4.07.1
This code relies on camlp4 preprocessor which is deprecated and is no longer supported. Moreover, list comprehension is no longer a part of the Batteries library and is a separate package. So you need to install it using opam install pa_comprehension. You can still make your code work for OCaml 4.07.1, by issuing the following directives right after you start OCaml toplevel (or utop)
#use "topfind";;
#camlp4o;;
#require "pa_comprehension";;
The first directive (note you have to type # it is a part of the directive), enables ocamlfind in the toplevel (I think it is not needed in utop, but won't hirt). The next directive enables camlp4o syntax, so that all inputs are preprocessed. You're no longer coding in OCaml after that, but in camlp4o dialect. Finally, the last directive loads the preprocessor that supports list comprehensions.
To compile the code that uses list comprehension you need to specify the same options to the compiler (i.e., enable syntax, load the preprocessor), e.g.,
ocamlfind ocamlopt -syntax camlp4o -package pa_comprehension -linkpkg example.ml -o example
The camlp4 package also provides another list comprehension syntax, which is a little bit different from the one that is provided by Batteries. It is called camlp4.listcomprehension, and you can use it with roughly the same invocations modulo the package name, e.g., in toplevel,
#use "topfind";;
#camlp4o;;
#require "camlp4.listcomprehension";;
and to compile
ocamlfind ocamlopt -syntax camlp4o -package camlp4.listcomprehension -linkpkg example.ml -o example
With all that said, I highly discourage you from using camlp4 list comprehension in modern days. This is an obsolete technology.
Besides, your example is ill-formed, you're missing the ? character in the closing bracket, e.g., this is an example interaction with the toplevel,
# #use "topfind";;
# #camlp4o;;
# #require "pa_comprehension";;
# open Batteries;;
# [? x | x <- 1--10; x mod 2 = 0 ?];;
- : int Batteries.Enum.t = <abstr>

Ocaml: unknown directive `require'

When loading OCaml, I receive this message when loading ocaml at the terminal:
ocaml
OCaml version 4.07.1
Unknown directive `require'.
What is the problem exactly?
I had previously modified my ocamlinit file, because I had some problems. It now contains:
(* ## added by OPAM user-setup for ocamltop / base ## 3ec62baf6f9c219ae06d9814069da862 ## you can edit, but keep this line *)
(* Added by OPAM. *)
let () = try Topdirs.dir_directory (Sys.getenv "OCAML_TOPLEVEL_PATH")
with Not_found -> ()
;;
#require "yojson";;
#use "topfind";;
#camlp4o
#thread;;
Topfind.don't_load ["compiler-libs.toplevel"];;
#require "core.top";;
#require "core.syntax";;
(* ## end of OPAM user-setup addition for ocamltop / base ## keep this line *)
Edit:
I looked at this question before ocaml command line cannot find “topfind”, however I did not find it helpful, since nowhere in the answers was it specified that you need to run eval $(opam config env) every time before opening ocaml, as someone below has informed me. So I think this person's clarification is useful to have on this site for other people.
You shall put #use "topfind" before any #require directive. So put #require "yojson";; to the end of the .ocamlinit file (also it is a good idea to add it after the comment).
The #require directive is provided by the ocamlfind tool via the topfind script, which is loaded into the toplevel via the #use directive, which is a standard builtin directive for loading files. The topfind file initializes the ocamlfind system in the toplevel, so that the toplevel now can access to the ocamlfind infrastructure and load libraries installed in the system. If you're using opam to install packages, then do not forget to do eval $(opam config env) (or a shorter version, available in opam 2.x eval $(opam env)) in your terminal, before starting the toplevel. E.g.,
eval $(opam config env)
ocaml
and here is the correct contents of the .ocamlinit file:
(* ## added by OPAM user-setup for ocamltop / base ## 3ec62baf6f9c219ae06d9814069da862 ## you can edit, but keep this line *)
(* Added by OPAM. *)
let () = try Topdirs.dir_directory (Sys.getenv "OCAML_TOPLEVEL_PATH")
with Not_found -> ()
;;
#use "topfind";;
#camlp4o
#thread;;
Topfind.don't_load ["compiler-libs.toplevel"];;
#require "core.top";;
#require "core.syntax";;
(* ## end of OPAM user-setup addition for ocamltop / base ## keep this line *)
#require "yojson";;

Use ocamlfind with ocaml interpreter, without compiling

I have a file main.ml that uses some package that makes the command ocaml main.ml fail and report this error:
Error: Unbound module X
And the only solution I've found so far is to run:
ocamlbuild main.native -use-ocamlfind -package X
./main.native
But this compiles the file. Is there a way to just run the regular ocaml interpreter (ocaml main.ml) with some additional flags to make it find the package?
The easiest way is probably to use topfind and add #require "core" at the top of your file. If you want to avoid adding toplevel directives in your file, you can use ocamlfind query -i-format -r to compute the required include directories:
ocaml $(ocamlfind query -i-format -r core) main.ml
You can put at the beginning of your file some top-level directives which find and load needed modules. For example, when I want to use Core library in my script I insert:
#use "topfind";;
#thread;;
#require "core";;
open Core.Std
(* Code of my script *)
To use topfind package ocamlfind has to be installed (opam install ocamlfind)
You can also query the path of your package to ocamlfind :
ocamlfind query package_X
That will return the path of your package : /path_to/packageX
And then :
ocaml main.ml -I /path_to/packageX

replace camlp4 with camlp5 in utop

I'm working with OCaml code that needs camlp5; however, the toplevel (I'm using utop) automatically loads the newer, incompatible camlp4. These are the startup messages:
Findlib has been successfully loaded. Additional directives:
#require "package";; to load a package
#list;; to list the available packages
#camlp4o;; to load camlp4 (standard syntax)
#camlp4r;; to load camlp4 (revised syntax)
#predicates "p,q,...";; to set these predicates
Topfind.reset();; to force that packages will be reloaded
#thread;; to enable threads
The .ocamlinit im using looks like this:
#use "topfind";;
#thread;;
I installed camlp5 with opam and it shows up when I issue ocamlfind list; also the file camlp5.cma is located in /home/<username>/.opam/4.02.1/lib/camlp5/camlp5.cma.
But trying to load camlp5o and camlp5r fails with Unknown directive camlp5o.
How can i make utop aware of camlp5 and how can I replace camlp4 with camlp5 as the default preprocessor?
Many thanks in advance!
$ ocaml
OCaml version 4.02.1
Findlib has been successfully loaded. Additional directives:
#require "package";; to load a package
#list;; to list the available packages
#camlp4o;; to load camlp4 (standard syntax)
#camlp4r;; to load camlp4 (revised syntax)
#predicates "p,q,...";; to set these predicates
Topfind.reset();; to force that packages will be reloaded
#thread;; to enable threads
# #require "camlp5";;
/home/kakadu/.opam/4.02.1/lib/camlp5: added to search path
# #load "camlp5o.cma";;
Camlp5 parsing version 6.12
#

Ocaml utop library paths, Core module

I am attempting to use the Core module in utop, as originated by Jane Street and installed using opam.
Here's the problem
utop # open Core.Std;;
Error: Unbound module Core
utop does not seem to have the path to the Core module.
How do you specify a path that can be found by utop to access the Core module? Is there a utop init file that specifies library paths ?
I have the same error message from the OCaml 4.01.0 interpreter.
The only way I can avoid this error is actually changing directory to /Users/myname/.opam/system/lib/core.
I had the same problem, the directions here got it working for me.
https://github.com/realworldocaml/book/wiki/Installation-Instructions#setting-up-and-using-utop
add the following lines to your ~/.ocamlinit file
#use "topfind";;
#thread;;
#camlp4o;;
#require "core.top";;
#require "core.syntax";;
Assuming that you have core properly installed through opam:
# require "core";;
open Core.Std;;
Should work.