1
votes

I know that in order to load a program in OCaml one has to type #use "source_code_file.ml" in toplevel where source_code_file.ml is the file we want to use.

My program reads input from stdin. In the command line i have a txt file that with redirection is used to act as stdin. Can i do this in toplevel? I would like to this because in toplevel i can easily see what type variables have and if things are initialized with the correct values.

1

1 Answers

1
votes

If you're on a Unix-like system you can use Unix.dup2 to do almost any kind of input redirection. Here is a function with_stdin that takes an input file name, a function, and a value. It calls the function with standard input redirected from the named file.

let with_stdin fname f x =
    let oldstdin = Unix.dup Unix.stdin in
    let newstdin = Unix.openfile fname [Unix.O_RDONLY] 0 in
    Unix.dup2 newstdin Unix.stdin;
    Unix.close newstdin;
    let res = f x in
    Unix.dup2 oldstdin Unix.stdin;
    Unix.close oldstdin;
    res

If your function doesn't consume the entire input the leftover input will confuse the toplevel. Here's an example that does consume its entire input:

# let rec linecount c =
  try ignore (read_line ()); linecount (c + 1)
  with End_of_file -> c;;
val linecount : int -> int = <fun>
# with_stdin "/etc/passwd" linecount 0;;
- : int = 86
#

This technique is too simple if you wanted to interleave interactions with the toplevel with calls to your function to consume just part of its input. I suspect that would make things too complicated to be worth the effort. It would be much easier (and perhaps better overall) to rewrite your code to work with an explicitly specified input channel.