I want to read a number but when i try to compile it it gives me Exception: End_of_file in the line read_int()
What am I doing wrong?
let k = read_int() ;;
let exercicio k=
Printf.printf "%d\n" k;
;;
If you want an online IDE which accept inputs, check : https://betterocaml.ml .
So far the best you will be able to find on internet. If you want a local install on windows check also https://github.com/gmattis/SimpleOCaml/.
The only issue with betterOCaml is that it doesn't handle infinite while loop, so be sure to save your file before running any programme with a while inside.
Related
I'm starting out with Haskell and was looking into I/O mechanims. I read up on the interact function which takes a function of type String -> String as parameter. I tried to write a simple program that takes to numbers from stdin and creates a list and prints it line by line.
import Data.List
readIn = sort . map read . words
writeOut = unlines . map show
rangeList [n,m] = [n .. m]
main = interact (writeOut . rangeList . readIn)
For some reason it wont print the numbers. Could you help me out?
interact requires you to input an end-of-file (EOF) to stdin with Ctrl+D (or Ctrl+Z on Windows); when I type that combination, the output appears as required. This is necessary because, as the documentation for interact states, ‘the entire input from the standard input device is passed to [interact] as its argument’; due to this, you need to explicitly signal the place where stdin ends.
(By the way, I’m not even sure how you got your program to compile; GHC gives me lots of ‘ambiguous type’ errors when I try. I had to add type signatures to get it working, at which point I found the solution above to work.)
I'm trying to build a new frontend in Ocaml for a terminal based application. The main idea is the spawn a new process with Lwt:
let cmd = shell "./otherterminalapp" in
let p = open_process_full cmd;
And then later write stuff to the process' stdin, to execute commands in the external app.
Lwt_io.write_line p#stdin "some command" >>= (fun _ -> Lwt_io.flush p#stdin)
When I read the result from the command back in with Lwt_io.read_line_opt. How do I read till there aren't any lines left?
The problem I'm encountering is that my program just hangs at a certain point. When I read with read_line_opt, while I reached the end it seems like it's just waiting for the process to redirect new output.
How can I approach this?
A concrete example of what I'm trying to do:
(The terminal based application is ocamldebug)
Program source code:
open Lwt
open Lwt_unix
open Lwt_process
let () =
let run () =
let cmd = shell "ocamldebug test.d.byte" in
let dbgr = open_process_full cmd in
(((((((Lwt_io.write_line dbgr#stdin "info modules") >>=
(fun _ -> Lwt_io.flush dbgr#stdin))
>>= (fun _ -> Lwt_io.read_line_opt dbgr#stdout))
>>=
(fun s ->
(match s with
| Some l -> print_endline l
| None -> print_endline "nothing here! ");
Lwt_io.read_line_opt dbgr#stdout))
>>=
(fun s ->
(match s with
| Some l -> print_endline l
| None -> print_endline "nothing here! ");
Lwt_io.read_line_opt dbgr#stdout))
>>=
(fun s ->
(match s with
| Some l -> print_endline l
| None -> print_endline "nothing here! ");
Lwt_io.read_line_opt dbgr#stdout))
>>=
(fun s ->
(match s with
| Some l -> print_endline l
| None -> print_endline "nothing here! ");
Lwt_io.read_line_opt dbgr#stdout))
>>=
(fun s ->
(match s with
| Some l -> print_endline l
| None -> print_endline "nothing here! ");
Lwt.return ()) in
Lwt_main.run (run ())
If you would normally run ocamldebug with test.d.byte, you get the
following in your terminal:
OCaml Debugger version 4.03.0
(ocd) info modules
Loading program... done.
Used modules:
Std_exit Test Pervasives CamlinternalFormatBasics
(ocd)
When I execute the above program, I get the following printed:
OCaml Debugger version 4.03.0
(ocd) Loading program... Used modules:
Std_exit Test Pervasives CamlinternalFormatBasics
And here it just hangs..., my program doesn't exit. Even when I do
Ctrl-c/Ctrl-c in my terminal, there's an active ocamlrun process. The terminal however becomes responsive though.
I am missing something obvious here?
A call to Lwt.read_line_opt returns a deferred value, that will be determined in the future as Some data once the channel reads a newline-terminated string, or with None if the channel was closed. The channel will be closed if there was an end-of-file condition. For the regular files, the end-of-file condition occurs when the file pointer reaches the end of the file. For the pipes, that are used to communicate with the subprocess, the end-of-file condition occurs when the opposite side closes the file descriptor associated with the pipe.
The ocamldebug program doesn't close its inputs or outputs. It is an interactive program, that is ready to interact with a user for the infinite amount of time, or until a user closes the program, by either hitting Ctrl-D or using the quit command.
In your scenario, you wrote the info modules command into the channel's input. The process responded with the three lines (where each line is a piece of data terminated with the newline). Then the subprocess started to wait for the next input. You're not seeing the (ocd) prompt, because it is not terminated by the newline character. The program didn't hang-up. It is still waiting for the output from the subprocess, and the subprocess is waiting for the input from you (a dead lock).
If you really need to distinguish outputs from different commands, then you need to track the prompt in the subprocess output. Since the prompt is not terminated by the newline, you can't rely on the read_line* family of functions, since they are line buffered. You need to read all available characters and find the prompt in them manually.
On the other hand, if you do not really need to distinguish between the outputs of different commands, then you can ignore the prompt (actually, you may even filter it out, for the nicer output). In that case, you will have two concurrent subroutines - one would be responsible for feeding input, and another will read all the output, and dump it, without actually carrying about the contents of the data.
I'm trying to make something like the following:
x = scanf(stdin);
But it has to be in OCaml, I've been reading but I can't seem to find a proper way to do this, what I'm doing is a card game and in the beginning I want to ask the user of the game, through the terminal, the amount of players that are going to play and that's why I need to scan from standard in. Thank you very much in advance.
For such a simple task, scanf is probably overkill. You might want to use read_int to get started.
# read_int ();;
17
- : int = 17
(The second line here is typed by the user, i.e., me.)
You don't have to specify stdin, do something like:
print_string "Enter number of players: ";
let p = scanf "%d" (fun x:int -> x) in
print_int p;
print_newline()
As part of a Compiler Principles course I'm taking in my university, we're writing a compiler that's implemented in OCaml, which compiles Scheme code into CISC-like assembly (which is just C macros).
the basic operation of the compiler is such:
Read a *.scm file and convert it to an OCaml string.
Parse the string and perform various analyses.
Run a code generator on the AST output from the semantic analyzer, that outputs text into a *.c file.
Compile that file with GCC and run it in the terminal.
Well, all is good and well, except for this: I'm trying to read an input file, that's around 4000 lines long, and is basically one huge expressions that's a mix of Scheme if & and.
I'm executing the compiler via utop. When I try to read the input file, I immediately get a stack overflow error message. It is my initial guess that the file is just to large for OCaml to handle, but I wasn't able to find any documentation that would support this theory.
Any suggestions?
The maximum string length is given by Sys.max_string_length. For a 32-bit system, it's quite short: 16777211. For a 64-bit system, it's 144115188075855863.
Unless you're using a 32-bit system, and your 4000-line file is over 16MB, I don't think you're hitting the string length limit.
A stack overflow is not what you'd expect to see when a string is too long.
It's more likely that you have infinite recursion, or possibly just a very deeply nested computation.
Well, it turns out that the limitation was the amount of maximum ram the OCaml is configured to use.
I ran the following command in the terminal in order to increase the quota:
export OCAMLRUNPARAM="l=5555555555"
This worked like a charm - I managed to read and compile the input file almost instantaneously.
For reference purposes, this is the code that reads the file:
let file_to_string input_file =
let in_channel = open_in input_file in
let rec run () =
try
let ch = input_char in_channel in ch :: (run ())
with End_of_file ->
( close_in in_channel;
[] )
in list_to_string (run ());;
where list_to_string is:
let list_to_string s =
let rec loop s n =
match s with
| [] -> String.make n '?'
| car :: cdr ->
let result = loop cdr (n + 1) in
String.set result n car;
result
in
loop s 0;;
funny thing is - I wrote file_to_string in tail recursion. This prevented the stack overflow, but for some reason went into an infinite loop. Oh, well...
I am in trouble with OCaml, because I want to read the lines from a text file, and I'm using this code to do the job:
let parse3ac() =
let lines = ref "" in
let chan = open_in "3ac" in
try
while true do
lines := input_line chan;
print_string(!lines);
done;
with End_of_file -> close_in chan;print_string("End Of File");;
But it only prints in the console "End Of File", but the lines from the file, doesn't appears.
What is wrong with this code guys?
Thks 4 all!!!
Edited:
Actually I have discovered the reason it isn't working.
It is very simple, the code above works very well, but the file "3ac" that I had created previously using OCaml, wasn't properly closed, and then it would be impossible to read the file.
Thanks everybody, and like I said before the code works so everyone can use that.
Thanks .
This code works, I tested it and it writes the lines of the file 3ac (without newlines as you don't print them) and then "End Of File". Are you sure the file 3ac is not empty ?