Ocaml syntax quite weird - ocaml

I have this program in Ocaml that reads a line from keyboard and returns an int :
let get_int () =
print_string "Insert a number\n" ;
let input = read_line() in
let return__ = int_of_string( input )
;;
print_string "I'll print what you write : ";
print_int ( get_int() );
print_string "\n"
The problem is a syntax error on line 5, ";;" said the compiler.
I know that already exist functions that do this but I'm doing this to learn.
I read the official Ocaml documentation but I still don't get the syntax.
Someone that could explain me something about it?

Your get_int-binding has to end in an expression. You can get rid of the last let-binding there and return the int directly:
let get_int () =
print_string "Insert a number\n";
let input = read_line () in
int_of_string input;;

Related

Pretty-printing with a comment string prefixing a box

I am trying to generate a text file for use in another program. This program only has line-style comments. I want to pretty-print a comment that, whenever the line is broken, it is prefixed by //.
Here is what I have so far:
type elaborate_type = A | B
let elaborate_to_string = function
| A -> "OK, this is type A, but long"
| B -> "B"
let pp_elaborate chan v = Format.pp_print_string chan (elaborate_to_string v)
Format.printf "#[<hv2>{#,#[<hov>// Here is a long comment I want to break# // \
here, but also indent. It should also be the case that anything# // \
I put here (such as some complex printable term \"%a\") should# // \
only break if it has //, too).#]#,\
#[...#]\
#]#,}#."
pp_elaborate A
which gives the output
{
// Here is a long comment I want to break
// here, but also indent. It should also be the case that anything
// I put here (such as some complex printable term "OK, this is type A, but long") should
// only break if it has //, too).
...
}
Is there a way to do this without adding the //# to the end of each line I want to break?
A option to solving this issue is to update the newline function of the formatter to make it prints // right after the newline:
let add_double_slash_after_linebreak_and_before_indents fmt =
let fns = Format.pp_get_formatter_out_functions fmt () in
let out_newline () =
fns.out_newline ();
fns.out_string "//" 0 2
in
Format.pp_set_formatter_out_functions fmt { fns with out_newline}
let () =
let () =
add_double_slash_after_linebreak_and_before_indents Format.std_formatter
in
Format.printf "#[<v 2>This tests the formatting#,One line#,two line #]"
This tests the formatting
// One line
// two line val add_double_slash_after_linebreak_and_before_indents :
However, the double slashes // will appear at the start of the line independently of the indentation, if you prefer them to appear after the indentation, you can update the indentation function of the formatter instead:
let add_double_slash_after_linebreak_and_indents fmt =
let fns = Format.pp_get_formatter_out_functions fmt () in
let out_indent n =
fns.out_indent n;
fns.out_string "//" 0 2
in
Format.pp_set_formatter_out_functions fmt { fns with out_indent}
let () =
let () =
add_double_slash_after_linebreak_and_indents Format.std_formatter
in
Format.printf "#[<v 2>This tests the formatting#,One line#,two line #]"
This tests the formatting
//One line
//two line
Concerning your follow-up question, any \n in a string will mess up the formatting if there are printed with %s. You can avoid this issue by using pp_print_text which replaces and \n in the string by calls to pp_print_space and pp_force_line.

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?

Write a SML function that take the name of a file and return a list of char without spaces

In an exam i found this exercise:
"Write a function that take a file name (i.e. "text.txt") and return a list of char without blanks"
For example:
"text.txt" contains "ab e ad c"
the function must return -> [#"a",#"b",#"e",#"a",#"d",#"c"]
Which is the easiest way to solve the exercise?
I've tried to use the library "TextIO" and the function "input1" but i got stuck. I don't know how to implement the function recursively. Could someone help?
fun chars filename =
let
val f = TextIO.openIn filename
val s = TextIO.inputAll f
in
TextIO.closeIn f;
List.filter (fn c => c <> #" ") (explode s)
end

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