Printing promt before user input - ocaml

I am new to OCaml, and now I am trying to make a simple REPL.
let rec repl () =
print_prompt () ;
let input = Scanf.scanf "%s" (fun x -> x) in
if input = "" then repl ()
else print_endline input
let print_prompt () = print_string "> "
The problem now i am having is: when program starts, it does not display prompt immediately. It waits for my input and prints prompt along with my input.
What I want is:
> "user_input"
"user_input"
But i am getting :
"user_input"
> "user_input"
How can I fix this?

Using readline instead of Scanf :
val read_line : unit -> string
Flush standard output, then read characters from standard input until a newline character is encountered. Return the string of all characters read, without the newline character at the end.

Well, you didn't show the print_promt implementation, but I can guess, that it uses some buffered io function like print_string or printf. They print into an intermediate buffer and data will not be displayed unless flush is called. You can use flush or flush_all functions to do this manually. Also you can use a special specificator %! in printf formats string:
open Printf
let print_prompt () = printf "> %!"

This is almost certainly a buffering problem. In your print_prompt function, flush the standard output:
flush stdout

Related

Prompt for string and read and then display in OCaml

I've spent a few days playing around with OCaml
let prompt_user() = print_string "Enter a string\n";;
let read_user_input2() =
prompt_user();
input_line stdin;;
When run, nothing happens, but I can start entering information. Only after entering the string does the actual prompt appear:
# read_user_input();;
hello
Enter a string
You entered hello
- : string = "hello"
#
Can someone tell me how I should be reordering my program so that the prompt appears before the input stage?
Many TIA
The standard output channel is buffered, but print_string does not flush the buffer. print_endline and print_newline does, however, as does flush of course, so either of these should work:
let prompt_user () = print_endline "Enter a string"
let prompt_user () =
print_string "Enter a string";
print_newline ()
let prompt_user () =
print_string "Enter a string\n";
flush stdout

I am trying to read a string from stdin and flush it out to stdout but I can't find a Standard ML way

NOTE: I'm totally Newbie in Standard ML. I merely have basic F# knowledge.
This is a good ol' code in C
#include <stdio.h>
int main()
{
char str[100]; // size whatever you want
scanf("%s", str);
printf("%s\n", str);
return 0;
}
now, I want to make a Standard ML-version-equivalent of this code. so I tried this:
val str = valOf (TextIO.inputLine TextIO.stdIn)
val _ = print str
but my SML/NJ says this:
uncaught exception Option
raised at: smlnj/init/pre-perv.sml:21.28-21.34
I googled it, and I also searched this site, but I cannot find any solution which doesn't cause error.
does anyone knows it?
EDIT: I tried this code:
fun main =
let val str = valOf (TextIO.inputLine TextIO.stdIn)
in
case str
of NONE => print "NONE\n"
| _ => print str
end
but it also makes error:
stdIn:1.6-1.10 Error: can't find function arguments in clause
stdIn:4.9-6.33 Error: case object and rules don't agree [tycon mismatch]
rule domain: 'Z option
object: string
in expression:
(case str
of NONE => print "NONE\n"
| _ => print str)
This answer was pretty much given in the next-most recent question tagged sml: How to read string from user keyboard in SML language? -- you can just replace the user keyboard with stdin, since stdin is how you interact with the keyboard using a terminal.
So you have two problems with this code:
fun main =
let val str = valOf (TextIO.inputLine TextIO.stdIn)
in
case str
of NONE => print "NONE\n"
| _ => print str
end
One problem is that if you write fun main then it has to take arguments, e.g. fun main () = .... The () part does not represent "nothing" but rather exactly one thing, being the unit value.
The other problem is eagerness. The Option.valOf function will crash when there is no value, and it will do this before you reach the case-of, making the case-of rather pointless. So what you can do instead is:
fun main () =
case TextIO.inputLine TextIO.stdIn of
SOME s => print s
| NONE => print "NONE\n"
Using the standard library this can be shortened to:
fun main () =
print (Option.getOpt (TextIO.inputLine TextIO.stdIn, "NONE\n"))
I encourage you to read How to read string from user keyboard in SML language?

noob question on reading integer/string inputs in OCaml

I was trying some coding challenge in Hackerank, and I was wondering how to read a line of space-separated integers using OCaml.
I know if the input integers are newline separated,
then we could do
let recread_lines () =
try line = read_line ()
in line:: read_lines()
with End_of_file->[]
and then convert the list to list of int using
let ()=
let input = read_lines ()
in List.map int_of_string input.
I also know that we can read the first integer from a line of integers by doing:
let n1 =Scanf.scanf " %d" (fun x -> x)
From C, I know scanf method scans the line looking for structure defined in the parameter and then store the scanned values into the variables. I don't see the use of (fun x->x) at the end of the scanf method in OCaml.
I don't know how to read a line of integers though, so if you can point me in the right direction, I would be able to work on those challenges!
Here's a function to read a line of space-separated integers from stdin:
let read_ints () =
let line = read_line () in
let ints = Str.split (Str.regexp " *") line in
List.map int_of_string ints
This function will raise End_of_file if there are no more lines in the input.
You can adapt the regular expression if there are actually tabs mixed with the spaces (say).
(FWIW I have found over the years that the scanf family of functions is prone to behaving badly in the face of unexpected input. This isn't a problem with OCaml in particular, it's the same for all languages that have scanf. So I haven't used scanf for quite a few decades.)

OCAML Taking multiple arguments from stdin and operating on them one by one

I have written an interpreter using ocamllex and ocamlyacc, the lexer and the parser work correctly but currently they only parse the last .txt argument it receives as oppose to all of them in turn. For example, ./interpret one.txt two.txt three.txt only parses three.txt as oppose to parsing one.txt and then two.txt and then three.txt which is what I want. So for example the parse results are as follows:
one.txt -> "1"
two.txt -> "2"
three.txt -> "3"
On calling ./interpret one.txt two.txt three.txt the current output is: 3 but I want it to be 123
Here is my main class which deals with the stdin and stdout
open Lexer
open Parser
open Arg
open Printf
let toParse c =
try let lexbuf = Lexing.from_channel c in
parser_main lexer_main lexbuf
with Parsing.Parse_error -> failwith "Parse failure!" ;;
let argument = ref stdin in
let prog p = argument := open_in p in
let usage = "./interpreter FILE" in
parse [] prog usage ;
let parsed = toParse !argument in
let result = eval parsed in
let _ = parsed in
flush stdout;
Thanks for your time
There's not really enough code here to be able to help.
If I assume that the output is written by eval, then I see only one call to eval. But there's nothing here that deals with filenames from the command line, so it's hard to say more.
If you are planning to read input from files, then there's no reason to be using stdin for anything as far as I can tell.
(I know this is a very minor point, but this code doesn't constitute a class. Other languages use classes for everything, but this is a module.)
Update
Here's a module that works something like the Unix cat command; it writes out the contents of all the files from the command line one after the next.
let cat () =
for i = 1 to Array.length Sys.argv - 1 do
let ic = open_in Sys.argv.(i) in
let rec loop () =
match input_line ic with
| line -> output_string stdout (line ^ "\n"); loop ()
| exception End_of_file -> ()
in
loop ();
close_in ic
done
let () = cat ()
Here's how it looks when you compile and run it.
$ ocamlc -o mycat mycat.ml
$ echo test line 1 > file1
$ echo test line 2 > file2
$ ./mycat file1 file2
test line 1
test line 2

How to run program in OCaml toplevel with input from file?

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