writing main() to call a function - ocaml

I have an OCaml function that converts a string to an array. What is the canonical way of writing a "main" function to call this and print the array.
let createArray pattern patArray =
(* some unimportant way of setting all the elements in the array patArray
based on the string pattern *)
let main () =
let pattern = "Pattern" in
let patArray = Array.create (String.length pattern) 0 in
let res = createArray pattern patArray in
Array.iter ~f:(printf "%d ") patArray;; <------------------
main ()
1) In the above, if I leave out the ';;' , it does not work. What is the significance of that?
2) Instead of using a dummy binding "res" , can I somehow just write two statements to be executed sequentially , like so:
createArray pattern patArray
Array.iter ~f:(printf "%d ") patArray

Without the ;;, the parser cannot know that the main () call following that line is supposed to be a stand-alone expression (whitespace is not significant here).
You can use the following idiom instead:
let main () = ...
let () = main ()
The let () = expr idiom will evaluate an expression of type unit at that point. The initial let informs the parser that a new top-level let construct begins. Using ;; is an alternative way to tell the parser about the end of a top-level construct, but is primarily intended for interactive use.
In order to evaluate two expressions sequentially, separate them with a semicolon (use parentheses or begin ... end if you're unsure about precedence rules). For example:
let patArray = Array.create (String.length pattern) 0 in
createArray pattern patArray;
Array.iter ~f:(printf "%d ") patArray
Or, using begin and end to make precedence clearer:
let patArray = Array.create (String.length pattern) 0 in begin
createArray pattern patArray;
Array.iter ~f:(printf "%d ") patArray
end
Without the ;, the parser would not know whether Array.iter on the next line is supposed to an additional argument to the createArray call.

Related

If statements questions in OCaml

I am trying to write the following code in OCaml:
let a = 0
let b = 1
if a > b then
{
print_endline "a";
print_endline "a";
}
print_endline "b"
And then I encountered the following error:
File "[21]", line 4, characters 0-2:
4 | if a > b then
^^
Error: Syntax error
I have tried using the begin and end keywords.
If you're writing a program (rather than mucking about in a REPL), then there are only certain constructs which can exist at the top level of your program.
One of those is a binding. So the following is fine:
let a = 0
let b = 1
But a conditional expression (if/else) is not permitted. We can get around this by binding that expression to a pattern. Since print_endline will just return (), we can write:
let () =
...
Your use of { and } is incorrect in this situation, but you can grouped multiple expressions with ; and ( and ). Remember that ; is not a "statement terminator" but rather a separator.
let () =
if a > b then (
print_endline "a";
print_endline "a"
);
print_endline "b"
Note that if can only exist without a matching else if the entire expression returns unit. This meets that criteria.

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.

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

how to safely discard an unsused variable in OCAML

Here's the part of my code :
(* Read the input file *)
let a = input_char inc in
(* Check if a is a number *)
if char_is_number a then
(* Read the second letter *)
let b = input_char inc in
(* Discard the space *)
input_char inc;
Where inc is a input_channel. It's reading from a .map file ( by the way, if you have good libraries that I am unaware of that can handle .map file I would gladly take it ) input_char will read the next character.
Basically, I'm reading 1 number and a character. The 3rd should be a space ( I will be doing these verification later ) and will be discarded.
My current code raises a warning, saying the last line should be unit
Is there a safe/elegant/right way to discard the next character read?
To ignore the return value of an expression, you simply need to use ignore function which serves exactly this purpose.
let b = input_char inc in
ignore(input_char inc);
To parse sufficiently complex files, you probably should consider OCamllex + Menhir, especially if you ever used lex/flex & yacc/bison.
While ignore will do what you want, it looks like using the wildcard pattern, _, might suit you better in this case, since you're otherwise assigning to "variables".
Consider
let b = input_char inc in
let _ = input_char inc in
let c = input_char inc in
...
vs
let b = input_char inc in
ignore (input_char inc);
let c = input_char inc in
...
The wildcard pattern, which you might have come across when using match, matches anything and then simply discards the value without binding it to a name. You can use any pattern with the let <pattern> in <expression> construct.