I am used to using the standard function print_int in OCaml, but when I open the library Base by Jane Street, as recommended in the book Real World OCaml, I obtain a deprecation warning:
utop # print_int;;
- : int -> unit = <fun>
utop # open Base;;
utop # print_int;;
Line 1, characters 0-9:
Alert deprecated: Base.print_int
- : int -> unit = <fun>
Even worse, when I build it with dune, as recommended in that book, warnings become errors. What should I do ? Replace print_int with printf "%i" ? or with Caml.print_int ? Both seem to work but look needlessly complicated. Something else ?
Thank you.
This is answered here: https://ocaml.janestreet.com/ocaml-core/v0.13/doc/base/index.html#using-the-ocaml-standard-library-with-base
Base is intended as a full stdlib replacement. As a result, after an open Base, all the modules, values, types, etc., coming from the OCaml standard library that one normally gets in the default environment are deprecated.
In order to access these values, one must use the Caml library, which re-exports them all through the toplevel name Caml: Caml.String, Caml.print_string, ...
Related
I'm very new to OCaml and recently studying on program verification.
For implementation, I need a library module of Ocaml that gets a result of another Ocaml program. I hope the library has the same functions as the ProcessBuilder in JAVA.
I wonder if there is such one for Ocaml.
Sure, OCaml provides facilities to create processes. Here is an example, showing how to use the Unix.open_process_in function,
# let input = Unix.open_process_in "echo 'hello, world'";;
val input : in_channel = <abstr>
# input_line input;;
- : string = "hello, world"
# input_line input;;
Exception: End_of_file.
You can spawn a process that runs any program, no matter in which language it is written. If you want your processes to communicate OCaml data structures, then you can use the Marshal module to safely translate your OCaml values to and from strings.
The following code from Real World OCaml Chapter 17: Data Serialization with S-Expressions page 339 is not compiling on utop:
type http_server_config = { web_root: string;
port: int with default(80);
addr: string with default("localhost");
} [##deriving sexp] ;;
It is complaining about the with in port: int with default(80);
Thanks!
In recent versions of the Janestreet's Core library, all syntax extensions have been converted from camlp4 extensions to ppx extensions. Consequently, you unfortunately need to adapt the syntax of all examples using syntax extensions in Real World OCaml.
Fortunately, contrarily to camlp4 extensions, ppx extensions cannot wildly modify OCaml syntax. At most they can use a slightly extended syntax compared to vanilla OCaml, wich adds extension nodes and attributes.
In particular, this means that since field:type with … is not synctatically valid for vanilla OCaml, it is also not a valid syntax with the ppx_sexp_conv extension enabled. In your case, the default value annotation needs to be written as an attribute of the corresponding record fields:
type http_server_config = {
web_root: string;
port: int [#default 80];
addr: string [#default "localhost"];
} [##deriving sexp] ;;
Note that in order to work in utop you need first to have required the
ppx_sexp_conv extension and opened the default runtime module:
#require "ppx_sexp_conv";;
open Sexplib.Std ;;
type http_server_config = {
web_root: string;
port: int [#default 80];
addr: string [#default "localhost"];
} [##deriving sexp] ;;
The examples in Real World OCaml assume you have Core installed, which includes some syntax extensions. I followed the installation instructions here and I still see the same problem you're seeing.
When I tried to install the syntax extending module, I saw this:
utop # #camlp4o;;
utop was built without camlp4 support.
So, I conclude that it's a little bit tricky to set up the environment that Real World OCaml is expecting.
At any rate, #Basile_Starynkevitch is correct. The code is using syntax extensions that aren't supported in your utop.
I have a program that uses the Bytes module from the Ocaml standard library and also opens the Core_kernel.Std module at the top of the file
open Core_kernel.Std
...
let let buf = Bytes.make bom_len '\x00' in
The problem I am having is that the latest version of Core_kernel introduced a new Bytes module that is shadowing the one from the standard library, which is resulting in a Unbound value Bytes.make compilation error.
Is there a way to solve this naming issue without getting rid of the open at the top of the file? If I did that it would require changing lots of things.
You could provide an alternative name for the Bytes module as such:
module B = Bytes
open Core_kernel.Std
let buf = B.make 10 '\x00'
and then do a search-replace in your code to change Bytes by B.
Another solution would be to avoid using open, but this would require a lot of changes in your code, I guess.
Core_kernel provides Caml module that binds everything that is available in standard library.
So, you could write this as
open Core_kernel.Std
...
let buf = Caml.Bytes.make bom_len '\x00' in
Unfortunately, Caml.Bytes is added only in 113.00.00 version that is not in OPAM yet.
Consider this very basic module definition:
module type My_test = sig
type config with sexp
end;;
When I directly enter this on the utop prompt, everything works fine:
utop # module type My_test = sig
type config with sexp
end;;
module type My_test =
sig type config val config_of_sexp : Sexp.t -> config val sexp_of_config : config -> Sexp.t end
But when I try to #use a file containing the exact same definition, I get an Unbound type constructor _no_unused_value_warning_ error:
utop # #use "dummy.mli";;
File "dummy.mli", line 2, characters 7-13:
Error: Unbound type constructor _no_unused_value_warning_
(line 2 is type config with sexp )
Version info: The universal toplevel for OCaml, version 1.7, compiled for OCaml version 4.01.0
UPDATE:
I'm starting a bounty since I'd really be interested in
knowing whether this is an OCaml bug
sensible workarounds / fixes for my code
1) The ocaml top-level has two undocumented options named: -dsource & -dparsetree
2) If I enable the -dsource and then try the #use "dummy.mli". I saw that the source that was generated looked like this:
$ ocaml -dsource
# #use "dummy.mli";;
module type My_test =
sig
type config
val config_of_sexp : (Sexplib.Sexp.t -> config) _no_unused_value_warning_
val sexp_of_config : (config -> Sexplib.Sexp.t) _no_unused_value_warning_
end;;
File "dummy.mli", line 1, characters 31-37:
Error: Unbound type constructor _no_unused_value_warning_
3) however, when I directly enter the type declaration directly into the toplevel the source generated did not have the "_no_unused_value_warning_"
4) The parse-tree that is generated for these two cases is slightly different, due to the presence of _no_unused_value_warning_.
5) After some greping I saw that the type_conv library inserts `'val name : _no_unused_value_warning_' as a sort of hack to deactivate warnings -- https://github.com/janestreet/type_conv/blob/master/lib/pa_type_conv.ml -- there is a comment starting on line 916 that explains this stuff (I am still learning ocaml, so I don't yet understand everything about these parts)
Since sexplib uses type_conv, this signature was added in this case.
6) But, the real issue here has to be be how the ocaml toplevel handles the #use directive and the directly input lines of code.
In this file: https://github.com/diml/ocaml-3.12.1-print/blob/master/toplevel/opttoploop.ml
-- use_file (at line 316) uses List.iter to loop over a list of Parsetree.toplevel_phrase and calls execute_phrase on each element.
The REPL loop (at line 427) calls execute_phrase on a single Parsetree.toplevel_phrase
7) I am still not sure what is really causing the difference in the parse-tree - but trying to figure it out was interesting.
It would be awesome if someone who understands these parts more posted an answer.
I ran into this today using utop 1.17 with Ocaml 4.02.1. After reading gautamc'e excellent answer, I tried this simple workaround:
utop # type 'a _no_unused_value_warning_ = 'a;;
This allowed me to successfully #use the module I had been having a problem with.
I start to learn Standard ML, and now I try to use Standard ML of New Jersey compiler.
Now I can use interactive loop, but how I can compile source file to standalone executable?
In C, for example, one can just write
$ gcc hello_world.c -o helloworld
and then run helloworld binary.
I read documentation for SML NJ Compilation Manager, but it don`t have any clear examples.
Also, is there another SML compiler (which allow standalone binary creating) available?
Both MosML and MLton also have the posibility to create standalone binary files. MosML through mosmlc command and MLton through the mlton command.
Note that MLton doesn't have an interactive loop but is a whole-program optimising compiler. Which in basic means that it takes quite some time to compile but in turn it generates incredibly fast SML programs.
For SML/NJ you can use the CM.mk_standalone function, but this is not advised in the CM User Manual page 45. Instead they recommend that you use the ml-build command. This will generate a SML/NJ heap image. The heap image must be run with the #SMLload parameter, or you can use the heap2exec program, granted that you have a supported system. If you don't then I would suggest that you use MLton instead.
The following can be used to generate a valid SML/NJ heap image:
test.cm:
Group is
test.sml
$/basis.cm
test.sml:
structure Test =
struct
fun main (prog_name, args) =
let
val _ = print ("Program name: " ^ prog_name ^ "\n")
val _ = print "Arguments:\n"
val _ = map (fn s => print ("\t" ^ s ^ "\n")) args
in
1
end
end
And to generate the heap image you can use: ml-build test.cm Test.main test-image and then run it by sml #SMLload test-image.XXXXX arg1 arg2 "this is one argument" where XXXXX is your architecture.
If you decide to MLton at some point, then you don't need to have any main function. It evaluates everything at toplevel, so you can create a main function and have it called by something like this:
fun main () = print "this is the main function\n"
val foo = 4
val _ = print ((Int.toString 4) ^ "\n")
val _ = main ()
Then you can compile it by mlton foo.sml which will produce an executable named "foo". When you run it, it will produce this as result:
./foo
4
this is the main function
Note that this is only one file, when you have multiple files you will either need to use MLB (ML Basis files) which is MLtons project files or you can use cm files and then compile it by mlton projectr.mlb