How to read a file, and write it to a different file - ocaml

I hope all is well. At this point, I plan on reading a file, and then writing it to another file. (The equivalent of cp in OCaml, before I go ahead and manipulate text.) Currently in my code, I am making using the extlib to read a file, and then output it. I am also using dune to build file as an executable file. My file looks something like the following:
(* example.ml file *)
let read_filename = "example_1.ts"
let filename = "example_2.ts"
let () =
let text read_filename =
let chan = open_in read_filename in
Std.input_list chan
let filename = filename in
let text = text in
Std.output_file ~filename ~text
(* normal exit: all channels are flushed and closed *)
When I build the file using dune build example.bc I receive the following error:
File "example.ml", line 11, characters 2-5:
Error: Syntax error
I am trying to figure out what I am doing wrong, but to no avail. Any help would be more than appreciated. Thank you.

When I have readed you code I remark these lines.
let filename = filename in
let text = text in
Why have you writting this line ? (* You could delete it safely *)
And then I have found your syntax error was a line above you have forgotten a in
(* example.ml file *)
let read_filename = "example_1.ts"
let filename = "example_2.ts"
let () =
let text read_filename =
let chan = open_in read_filename in
Std.input_list chan
in
Std.output_file ~filename ~text
(* normal exit: all channels are flushed and closed *)
The rule for each local definition you must have a in keyword
(* a local definition is a let inside a let expression *)

Related

[OCaml flow_parser) No implementations provided for the following modules

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).

Type error when passing Ocaml a file from the command line but not in repl

My code gives an error when run from a file but runs fine when pasted into the Ocaml repl. I have saved the following as test.ml:
module StringSet = Set.Make(String)
let words = StringSet.add StringSet.empty "something";;
When run from bash with "ocaml test.ml" I get:
File "test.ml", line 3, characters 26-41:
Error: This expression has type StringSet.t = Set.Make(String).t
but an expression was expected of type StringSet.elt = string
When pasted into the Ocaml repl I get:
# module StringSet = Set.Make(String)
let words = StringSet.add StringSet.empty "something";;
module StringSet :
sig
(* ... much more output ... *)
end
val words : StringSet.t = <abstr>
#
Everything seems to work fine from the repl.
My Ocaml version is reported by the repl as: OCaml version 4.02.1.
Does anyone know why the error is produced when running "ocaml test.ml"?
The StringSet.add function takes the element (the string) as the first parameter and the set (StringSet.empty) as the second parameter. You have them in the opposite order.
When I try your code I get the same error in both cases. When I invert the parameter order I don't get an error in either case.
I'm using OCaml 4.06.0, but I would really doubt that the paramter order has changed.

Formatting text file in Python

I want to format an existing text file, the contents of text file are:
Aurangabad
Adilabad
Beed
I want to format it like:
Aurangabad|Aurangabad,
Adilabad|Adilabad,
Beed|Beed,
I am not so good in Python file handling.
the code to do so:
with open('file_name.txt','r') as file:
list_of_lines = file.readlines()
new_lines_list = []
for line in list_of_lines:
line = line.replace('\n','') #because each line end with this and we don't need it now (\n is the newline chr)
new_lines_list.append('{0}|{0}\n'.format(line)) #the same as - new_lines_list.append(line+'|'+line+'\n')
with open('file_name.txt','w') as file:
string_to_write = ''.join(new_lines_list)
file.write(string_to_write)
if you don't understand the with statement: it is basically to open the file and at the end it will close itself (and even if some exception occur it will still close (I explain bad if you don't understand go here)

Writting and reading a custom variable to a file in Ocaml

I'm trying to write and then read a variable to a file. The variable is from a data type created by me.
(If helps:
type sys =
File of string * string list | Folder of string * sys list ;;
)
How can I do this?
I've been reading about the use of fprintf, but for what I get it'd had to be converted somehow into a String first, right?
If you are sure your type will not change, you can use input_value and output_value from Pervasives.
let write_sys sys file =
let oc = open_out file in
output_value oc sys;
close_out oc
let read_sys file =
let ic = open_in file in
let sys : sys = input_value ic in
close_in ic;
sys
read_sys will break whenever you will try to read value stored with an other version of sys (or if you change your version of OCaml between writing and reading).
If you want safety, you can use automatic serializer such as sexplib (if you want to be able to read the file you are creating) or biniou for efficient conversion.

Scripted main in OCaml?

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.