Currently I have some code in this way:
method printFuncIntoFile X =
let funHead = "head"
and funbody = "body"
and oc = open_out "test.txt" in
Printf.fprintf oc "%s%s" funHead funBody;
close_out oc;
foo X.child
And this code can only leave the last function content in the text.txt.
I search the Printf document but can only find a
val bprintf : Buffer.t -> ('a, Buffer.t, unit) format -> 'a
which requires a Buffer data structure, I think there should be some strategies more easy, even though I don't know
So my question is that:
How to print into file in OCaml in a appending way?
You should be able to use:
open_out_gen [Open_append; Open_creat] 0o666 "test.txt"
Note that opening channels isn't part of Printf, but part of the Pervasives module.
Related
I want to retrieve the list of direct files (i.e. no recursive search) of a given directory and a given extension in OCaml.
I tried the following but:
It does not look OCaml-spirit
It does not work (error of import)
let list_osc2 =
let list_files = Sys.readdir "tests/osc2/expected/pp" in
List.filter (fun x -> Str.last_chars x 4 = ".osc2") (Array.to_list list_files)
I got the error (I am using OCamlPro):
Required module `Str' is unavailable
Thanks
You can use Filename.extension instead of Str.last_chars:
let list_osc2 =
let list_files = Sys.readdir "tests/osc2/expected/pp" in
List.filter (fun x -> Filename.extension x = ".osc2") (Array.to_list list_files)
and then use the pipe operator to make it a bit more readable:
let list_osc2 =
Sys.readdir "tests/osc2/expected/pp"
|> Array.to_list
|> List.filter (fun x -> Filename.extension x = "osc2")
I don't know how you expect this to work in OCamlPro though, as it doesn't have a filesystem as far as I'm aware.
To use the Str module, you need to link with the str library. For example, with ocamlc, you need to pass str.cma, and with ocamlopt, you need to pass str.cmxa. I don't know how to do that with OcamlPro.
In any case, Str.last_chars is not particularly useful here. It doesn't work if the file name is shorter than the suffix. By the way, your code would never match because ".osc2" is 5 characters, which is never equal to last_chars x 4.
The Filename module from the standard library has functions to extract and check a file's extension. You don't need to do any string manipulation.
I don't know what you consider “ugly as hell”, but apart from the mistake with string manipulation, I don't see any problem with your code. Enumerating the matches and filtering them is perfectly idiomatic.
let list_osc2 =
let list_files = Sys.readdir "tests/osc2/expected/pp" in
List.filter (fun name -> check_suffix name ".osc2") (Array.to_list list_files)
I have the following ocaml code:
let rec c_write =
"printf(\" %d \");\n"
On calling this function in the interpreter, I expect to get the output
printf("%d"); followed by a new line, but instead I get
printf(\" %d \");\n
How can I get my expected output when I'm calling the function without using any other I/O functions?
The expression let rec c_write = "printf(\" %d \");\n" is not a function. It is a value of type string which is bound to a variable named c_write. So you're not using any I/O functions in your code.
When entered in the interactive toplevel, this value is printed by the interpreter evaluation loop for user convenience. The same as when a Python interpreter will print for you the value that you've just entered.
The representation, chosen by the OCaml toplevel interpreter, in general, has nothing to do with the representation which is used to store a value in a file or to print it. Moreover, in OCaml, there is no canonical representations.
If you want to write a function that prints a C printf statement then this is how it will look like in OCaml
let print_printf () =
print_endline {|printf("%d");|}
In the example above, I've used {||} to denote a sting literal instead of more common "", since in this literal there is no need to escape special characters and they are interpreted literally (i.e., the don't have any special meaning).
You can achieve the same result using the regular "" quotes for denoting it
let print_printf () =
print_endline "printf(\"%d\");"
Here is an example of the toplevel interaction using these definitions:
# let print_printf () =
print_endline {|printf("%d");|};;
val print_printf : unit -> unit = <fun>
# print_printf ();;
printf("%d");
- : unit = ()
# let print_printf () =
print_endline "printf(\"%d\");";;
val print_printf : unit -> unit = <fun>
# print_printf ();;
printf("%d");
- : unit = ()
If you will put this code in a file, compile, and execute and redirect into a C file it will be a well-formed C file (modulo the absence of the function body).
Since you are somehow using the toplevel printer for printing, and that you somehow needs a very specific format, you need to install a custom printer.
The following would work:
# #install_printer Format.pp_print_string;;
# " This \" is not escaped " ;;
- : string = This " is not escaped
However, it seems very likely that this is not really the problem that you are trying to solve.
I think that what i mean is in the title. I have tried to search if it is possible to run bash script from ocaml like from java or from php but i could not find.
i know that we can use ocaml as a scripting language but it is not what i want
Ocaml as a scripting language
In other words
From the Ocaml documentation :
val command : string -> int
So if you want to call a script from Ocaml, do this :
let status = Sys.command "./myexecutable.sh" in
Printf.printf "status = %d\n" status
Feel free to do what you want with the exit code.
Just in case you are interested in collecting the output of the bash script,
let () =
(* Just using pstree as an example, you can pick something else *)
let ic = Unix.open_process_in "pstree" in
let all_input = ref [] in
try
while true do
all_input := input_line oc :: !all_input
done
with
End_of_file ->
(* Just an example, you can do something else here *)
close_in ic;
List.iter print_endline !all_input
I think what you are looking for is the Sys module (http://caml.inria.fr/pub/docs/manual-ocaml/libref/Sys.html).
Sys.command might be one way to do what you want.
If this is not enough, then you may want to take a look at what the Unix has to offer (http://caml.inria.fr/pub/docs/manual-ocaml/libref/Unix.html).
Me coming from a c# and python background, feels there must be a better way to read a file and populate a classic F# list. But then I know that a f# list is immutable. There must be an alternative using a List<string> object and calling its Add method.
So far what I have at hand:
let ptr = new StreamReader("stop-words.txt")
let lst = new List<string>()
let ProcessLine line =
match line with
| null -> false
| s ->
lst.Add(s)
true
while ProcessLine (ptr.ReadLine()) do ()
If I were to write the similar stuff in python I'd do something like:
[x[:-1] for x in open('stop-words.txt')]
Simple solution
System.IO.File.ReadAllLines(filename) |> List.ofArray
Although you can write a recursive function
let processline fname =
let file = new System.IO.StreamReader("stop-words.txt")
let rec dowork() =
match file.ReadLine() with
|null -> []
|t -> t::(dowork())
dowork()
If you want to read all lines from a file, you can just use ReadAllLines. The method returns the data as an array, but you can easily turn that into F# list using List.ofArray or process it using the functions in the Seq module:
open System.IO
File.ReadAllLines("stop-words.txt")
Alternatively, if you do not want to read all the contents into memory, you can use File.ReadLines which reads the lines lazily.
My function is trying to read a textfile line by line and carry out a certain predefined function on each line called somefn and append the value of somefn to the function. The somefn is already defined above this and works fine.
fun extractline(infile:string)=
let
val insl=TextIO.inputLine(ins)
case insl of
NONE=> []
|SOME(l)=>somefn(insl)::extractline(infile)
in
TextIO.closeIn(ins);
end
;
I am having errors and cannot handle them.
I would appreciate some help.
Thank You.
Remember, in let ... in ... end blocks, you place declarations you need between let and i n, and the resulting expression between in and end.
As such, you need your case expression placed between in and end.
You also never open the stream, ins. Make your function open the stream, and then work recursively on that stream in another function, however; you don't want to open the file for each recursive call.
You'll want something on this form:
fun extractline file =
let
val ins = TextIO.openIn file
fun extractline_h () = (* do something with ins here *)
in
extractline_h () before
TextIO.closeIn ins
end
Then you make extractline_h be recursive, and build up the list in that.