Как запустить программу в OCaml на верхнем уровне с вводом из файла?

Я знаю, что для загрузки программы в OCaml нужно набрать #use "source_code_file.ml" в toplevel, где source_code_file.ml - это файл, который мы хотим использовать.

Моя программа читает ввод из стандартного ввода. В командной строке у меня есть текстовый файл, который с перенаправлением используется в качестве стандартного ввода. Могу ли я сделать это на высшем уровне? Я хотел бы этого, потому что на верхнем уровне я могу легко видеть, какие переменные типа имеют и если вещи инициализируются с правильными значениями.

1 ответ

Если вы работаете в Unix-подобной системе, вы можете использовать Unix.dup2 для почти любого вида перенаправления ввода. Вот функция with_stdin который принимает имя входного файла, функцию и значение. Вызывает функцию со стандартным вводом, перенаправленным из названного файла.

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

Если ваша функция не использует весь ввод, оставшийся ввод будет перепутать верхний уровень. Вот пример, который потребляет весь свой ввод:

# 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
#

Этот метод слишком прост, если вы хотите чередовать взаимодействия с верхним уровнем с вызовами вашей функции, чтобы использовать только часть ее ввода. Я подозреваю, что это сделало бы вещи слишком сложными, чтобы стоить усилий. Было бы намного проще (и, возможно, лучше) переписать ваш код для работы с явно указанным входным каналом.

Другие вопросы по тегам