I'm trying to use OUnit with OCaml.
The unit code source (unit.ml) is as follows:
open OUnit
let empty_list = []
let list_a = [1;2;3]
let test_list_length _ =
assert_equal 1 (List.length empty_list);
assert_equal 3 (List.length list_a)
(* etc, etc *)
let test_list_append _ =
let list_b = List.append empty_list [1;2;3] in
assert_equal list_b list_a
let suite = "OUnit Example" >::: ["test_list_length" >:: test_list_length;
"test_list_append" >:: test_list_append]
let _ =
run_test_tt_main suite
With ocamlc unit.ml, I got an error message Error: Unbound module OUnit. Why is this? How can I use the OUnit in OCaml. I installed OUnit with opam.
You should use for example:
ocamlfind ocamlc -package oUnit -linkpkg -o unit unit.ml
ocamlfind is an utility that encapsulates lookup of installed libraries. You can also avoid composing compiler-invocation yourself and use a build tool.
Related
I am trying to use the flow_parser library, but I get the following error after running dune exec ./start.exe:
File "_none_", line 1:
Error: No implementations provided for the following modules:
Ppx_deriving_runtime referenced from /Users/macintosh/.opam/4.07.1/lib/flow_parser/parser_flow.cmxa(File_key)
Here's my dune file:
(executables
(names start)
(libraries core flow_parser)
(preprocess (pps ppx_jane ppx_deriving.show ppx_deriving.ord)))
Here's the start.ml:
let () =
let source = File_key.SourceFile("./fixtures/fib.js") in
let channel = open_in "./fixtures/fib.js" in
let lexbuf = Sedlexing.Utf8.from_channel channel in
let lex_env = Lex_env.new_lex_env (Some source) lexbuf ~enable_types_in_comments: false in
let (_, lex_result) = Lexer.token lex_env in
print_endline(Lex_result.debug_string_of_lex_result(lex_result));
Note that I could not use open Flow_parser - I get an unbounded module error. However, my editor (VSCode with the OCaml/ReasonML plugin) allows me to access the modules inside Flow_parser (e.g. File_key).
I have searched in modules Sys, Gc, and Unix, but did not find a means to get the system page size in OCaml. How can we get the system page size?
I have OCaml 4.06 and macOS 10.12.6 (Sierra)
If you just want the answer for MacOS, there is a pagesize command that you can run with Unix.open_process_in:
$ rlwrap ocaml
OCaml version 4.06.0
# #load "unix.cma";;
# Unix.open_process_in "pagesize" |> input_line |> int_of_string;;
- : int = 4096
Update
There is a POSIX command line program getconf that is quite portable, I believe. It works on macOS and all the versions of Linux I tried. You can use that instead:
$ rlwrap ocaml
OCaml version 4.06.0
# #load "unix.cma";;
# Unix.open_process_in "getconf PAGE_SIZE" |> input_line |> int_of_string;;
- : int = 4096
You can call sysconf(SC_PAGESIZE) from ocaml to get that information. You can either do that using a .c file, or using ctypes (although you'll need the value of the SC_PAGESIZE, so it might not be the best solution):
% utop -require ctypes.foreign
# open Foreign;;
# open Ctypes;;
# let sysconf = foreign "sysconf" (int #-> returning long);;
val sysconf : int -> Signed.long = <fun>
# sysconf 30;;
- : Signed.long = <long 4096>
Here I have a file set.ml with a module called IntSet. How do I refer to the module IntSet inside the corresponding interface file set.mli?
module IntSet = struct
type t = int list;;
let empty = [];;
let rec is_member key = function
| [] -> false
| (x::xs) -> (
if x = key then true
else is_member key xs
);;
end;;
let join xs ys = xs # ys;;
Here is set.mli
val join : IntSet.t -> IntSet.t -> IntSet.t
If I try to compile it, I get an error claiming that the module IntSet is unbound.
% corebuild set.native
+ ocamlfind ocamlc -c -w A-4-33-40-41-42-43-34-44 -strict-sequence -g -bin-annot -short-paths -thread -package core -ppx 'ppx-jane -as-ppx' -o set.cmi set.mli
File "set.mli", line 1, characters 11-19:
Error: Unbound module IntSet
Command exited with code 2.
Hint: Recursive traversal of subdirectories was not enabled for this build,
as the working directory does not look like an ocamlbuild project (no
'_tags' or 'myocamlbuild.ml' file). If you have modules in subdirectories,
you should add the option "-r" or create an empty '_tags' file.
To enable recursive traversal for some subdirectories only, you can use the
following '_tags' file:
true: -traverse
<dir1> or <dir2>: traverse
Compilation unsuccessful after building 3 targets (1 cached) in 00:00:00.
How do I expose a module defined in set.ml so I can use it in definitions?
I changed set.mli to this, and the compiler seems happy:
module IntSet : sig type t end
val join : IntSet.t -> IntSet.t -> IntSet.t
There is probably more work to make things usable. There's no way to make a value of type IntSet.t, for example.
How can I emulate this Python idiom in OCaml?
if __name__=="__main__":
main()
See RosettaCode for examples in other programming languages.
There is no notion of main module in Ocaml. All the modules in a program are equal. So you can't directly translate this Python idiom.
The usual way in Ocaml is to have a separate file containing the call to main, as well as other stuff like command line parsing that only make sense in a standalone executable. Don't include that source file when linking your code as a library.
There is a way to get at the name of the module, but it's rather hackish, as it is intended for debugging only. It violates the usual assumption that you can rename a module without changing its behavior. If you rely on it, other programmers reading your code will curse you. This method is provided for entertainment purposes only and should not be used in real life.
let name_of_this_compilation_unit =
try assert false with Assert_failure (filename, _, _) -> filename
You can compare the name of the compilation unit with Sys.executable_name or Sys.argv.(0). Note that this is not really the same thing as the Python idiom, which does not rely on the toplevel script having a particular name.
$ ocamlc -o scriptedmain -linkall str.cma scriptedmain.ml
$ ./scriptedmain
Main: The meaning of life is 42
$ ocamlc -o test -linkall str.cma scriptedmain.ml test.ml
$ ./test
Test: The meaning of life is 42
scriptedmain.ml:
let meaning_of_life : int = 42
let main () = print_endline ("Main: The meaning of life is " ^ string_of_int meaning_of_life)
let _ =
let program = Sys.argv.(0)
and re = Str.regexp "scriptedmain" in
try let _ = Str.search_forward re program 0 in
main ()
with Not_found -> ()
test.ml:
let main () = print_endline ("Test: The meaning of life is " ^ string_of_int Scriptedmain.meaning_of_life)
let _ =
let program = Sys.argv.(0)
and re = Str.regexp "test" in
try let _ = Str.search_forward re program 0 in
main ()
with Not_found -> ()
Posted on RosettaCode.
I have just installed a library called Apron, the installation seems to be done:
#ubuntu$ find -name "*apron*"
./lib/libapron_debug.so
./lib/libapron.a
./lib/libapron.so
./lib/libapron_debug.a
./local/lib/ocaml/3.11.2/stublibs/dllapron_caml.so.owner
./local/lib/ocaml/3.11.2/stublibs/dllapron_caml.so
./local/lib/ocaml/3.11.2/apron
./local/lib/ocaml/3.11.2/apron/libapron_caml_debug.a
./local/lib/ocaml/3.11.2/apron/apron.cmxa
./local/lib/ocaml/3.11.2/apron/libapron_caml.a
./local/lib/ocaml/3.11.2/apron/apron.cmi
./local/lib/ocaml/3.11.2/apron/apron.cmx
./local/lib/ocaml/3.11.2/apron/apron.a
./local/lib/ocaml/3.11.2/apron/apron.cma
And I tried a first example:
(* with default setting:
apronppltop -I $MLGMPIDL_INSTALL/lib -I $APRON_INSTALL/lib
#load "gmp.cma";;
#load "apron.cma";;
#load "box.cma";;
#load "oct.cma";;
#load "polka.cma";;
#load "ppl.cma";;
#load "polkaGrid.cma";;
#install_printer Apron.Linexpr1.print;;
#install_printer Apron.Texpr1.print;;
#install_printer Apron.Lincons1.print;;
#install_printer Apron.Generator1.print;;
#install_printer Apron.Abstract1.print;;
let environment_print fmt x = Apron.Environment.print fmt x;;
let lincons1_array_print fmt x = Apron.Lincons1.array_print fmt x;;
let generator1_array_print fmt x = Apron.Generator1.array_print fmt x;;
#install_printer Apron.Var.print;;
#install_printer environment_print;;
#install_printer lincons1_array_print;;
#install_printer generator1_array_print;; *)
open Apron;;
...
However ocaml -c file.ml gives me Error: Unbound module Apron which happens on open Apron;;
Does anyone know why I could not load the Apron module? Thank you very much!
I should indicate the path of the Apron library with '-I' options. As it is installed in the standard library of OCaml, you only need to compile with:
ocamlc -I +apron -c file.ml