Ocaml recursion not printing int when inside another Function - ocaml

When I compile and Execute this piece of code. It prints nothing.
let main list =
let rec xyz list =
match list with
|[]->[]
|m::body ->
begin
print_int m;
xyz body
end
in xyz
let h = main [1;2;3]
If xyz is used outside of main is working without any error and printing 1 2 and 3

Compiling your code with all warning enabled yields the following warning:
1 | let main list =
^^^^
Warning 27 [unused-var-strict]: unused variable list.
And indeed, the argument list is unused by main since in
let main list =
let rec xyz list =
...
in
xyz
you are returning the function xyz without applying it.

Related

Need and purpose of `()` and `in` in ocaml code

I am trying to understand Ocaml and running following code from here:
let rec fib n =
if n < 2 then 1 else fib (n-1) + fib (n-2);;
let main () =
let arg = int_of_string Sys.argv.(1) in
print_int (fib arg);
print_newline ();
exit 0;;
main ();;
However, I cannot understand why () and in are needed and why following code (which is much cleaner) does not work:
let rec fib n =
if n < 2 then 1 else fib (n-1) + fib (n-2);;
let main =
let arg = int_of_string Sys.argv.(1);
print_int (fib arg);
print_newline;
exit 0;; (* Line 7. Error is coming from here.*)
main;;
Above code gives following error:
File "fib_simpler.ml", line 7, characters 8-10:
Error: Syntax error
I notice that removing () only give warning, while removing in gives error and program execution stops.
Keeping in and () after print_newline removes all warnings and errors. So () is not really needed with main keywords.
Above is shown in comments below:
let rec fib n = (*(n) also works here*)
if n < 2 then 1 else fib (n-1) + fib (n-2);;
let main () = (*removing () here does not matter*)
let arg = int_of_string Sys.argv.(1) in (* in keyword is essential here*)
print_int (fib arg);
print_newline (); (*removing () causes warning *)
exit 0;;
main ();; (*removing () here does not matter*)
Any explanation will be appreciated.
OCaml is an expression-based language. It does not have statements, and therefore ; is not a statement terminator, but a sequence operator (similar to the comma operator of C). <expr1>; <expr2> is approximately just a short-hand for let () = <expr1> in <expr2>. It evaluates expr1, discards its value, then evaluates expr2 and returns that value.
let <pattern> = <expr1> in <expr2> is an expressions which binds the result of expr1 according to <pattern>, which may just be a simple identifier or a more complex record pattern for example, in the context of expr2. The bindings created by <pattern> will not exist outside expr2.
Using (), called "unit" in a binding defines a function. If you omit the argument, you're not defining a function, just a value. The difference is that a value is evaluated immediately, and just once, while a function will be evaluated when it is "called" by applying arguments to it. A function that expects () as an argument must be given () as the argument to execute it, otherwise you're just passing the function itself around. And if you're just discarding it, as you do above, that is almost always an error. Hence the warning.
In short:
let arg = int_of_string Sys.argv.(1); ... without an in separating two expressions is a syntax error. The compiler just doesn't realize it until it gets to the end of the current expression and discovers there is no in to be found there.
let main () =... defines a function
let main = ... defines a value
print_newline (); ... applies the argument () to print_newline, thereby executing it, then discards the return value
print_newline; ... doesn't really do anything
Finally, if you're just going to execute main once, you can reduce
let main () = ...;;
main;;
to
let () = ...;;
You don't need a named function unless you're going to use it multiple times.

OCaml Triple every number in a list of integers

So I need to write a function that will triple every number in a list of integers
Here is what I have so far:
let number = [1; 2; 3; 4];;
let rec print_list_int myList = match myList with
| [] -> print_endline "This is the end of the int list!"
| head::body ->
begin
print_int head * 3;
print_endline "";
print_list_int body *3
end
;;
print_list_int number;;
It doesn't seem to do anything useful, any ideas where I went wrong? Need it outputting but it also doesn't do that. Thanks in advance! :)
This expression:
print_int head * 3
is interpreted like this:
(print_int head) * 3
Because function calls (application) have high precedence. You need to parenthesize like this:
print_int (head * 3)
The similar case below is a different problem: (print_list_int body) * 3 doesn't make sense but print_list_int (body * 3) also doesn't make sense. You can't multiply a list by 3. However, you don't need to multiply at this call. The print_list_int function will (recursively) do the multiplying for you.
Update
If I make the changes I hinted at above, I see this in the OCaml toplevel:
val print_list_int : int list -> unit = <fun>
# print_list_int number;;
3
6
9
12
This is the end of the int list!
- : unit = ()
#
Note that the most elegant way to achieve what you're trying to do is to use List.iter. It applies a given function (returning unit) to each element of a List.
let print_triples = List.iter (fun x ->
print_endline (string_of_int (3*x))
);;
val print_triples : int list -> unit = <fun>
And here you go:
# print_triples [1;2;3;4;5];;
3
6
9
12
15
- : unit = ()

Ocaml: add up all the integers in an int list and output it as an int Option

. Write a function that takes an integer list and return sum of all elements of the list. If the list is empty then return None.
This is my code now:
let rec sum (xs: int list) =
match xs with
| [] -> None
| [x] -> Some x
| hd::tl -> let m = (hd + (sum tl)) in
Some m
;;
The problem is that I can't seem to find a way to add up the last element without getting an error.
This is my error.
Error: This expression has type int but an expression was expected of type 'a option.
Your recursive call to sum does indeed return an int option. You know this because you're the author of the function, and you coded it up to return that type :-) You can either write a helper function that returns an int, or you can extract the int from the return value of sum, something like this:
let tlsum =
match sum tl with
| None -> (* figure this part out *)
| Some n -> (* figure this part out *)
You can define the addition of two int option.
let sum l =
let (+) a b =
match (a,b) with
| (None,x) | (x,None) -> x
| (Some x,Some y) -> Some (x+y)
in
let convert a = Some a in
let opt_l=List.map convert l in
List.fold_left (+) None opt_l
Test
# sum [];;
- : int option = None
# sum [1;2];;
- : int option = Some 3
That looks like an assignment so I'll be vague:
The easiest way to do that is probably to first define a function of type int list -> int that returns the "normal" sum (with 0 for the empty case). That function will be recursive and 0 will correspond to the base case.
Then write another function of type int list -> int option that checks whether its argument is empty or not and does the right thing based on that.
Trying to write the recursion directly probably is not a good idea since there are two cases when you will need to handle []: when it's the only element in the list, and when it's at the end of a nonempty list.

Implementing multiple if statements in OCaml

So I am a little new to OCaml and I am trying to figure out a way for my function to check multiple conditions and modify a variable if any of those conditions are true
rough pseudo code would be
var list = []
if cond1 then 1::list
if cond2 then 2::list
etc
but from what I am able to tell once you enter an if statement you stay in it until it returns a value to the function. Is there a way around this limitation? Thanks for your time, tips or hints are greatly appreciated as I would love to understand the language
OCaml variables are immutable, you can't change their values. So you need to think of this a different way. One reasonable thing would be to have a function whose value is equal to a supplied list with something added to the front:
let f list =
if cond1 then 1 :: list
else if cond2 then 2 :: list
else 3 :: list
Note that if in OCaml is an expression, i.e., it has a value. It's similar to the ?: ternary operator in languages influenced by C.
Here is an OCaml session that shows a function like this. It's just an example, this isn't a useful function:
$ ocaml
OCaml version 4.01.0
# let f list =
if List.length list > 3 then 1 :: list
else if List.length list > 1 then 2 :: list
else 3 :: list ;;
val f : int list -> int list = <fun>
# f [];;
- : int list = [3]
# f [1;2];;
- : int list = [2; 1; 2]
Update
If you want to apply the ifs all the time the code looks like this:
let f list =
let list' = if cond1 then 1 :: list else list in
let list'' = if cond2 then 2 :: list' else list' in
let list''' = if cond3 then 3 :: list'' else list'' in
list'''
You can capture the repeated pattern in its own function:
let f list =
let cpfx cond pfx l = if cond then pfx :: l else l in
cpfx cond3 3 (cpfx cond2 2 (cpfx cond1 1 list))
If you want to have a sequence of if statements, each if must return unit. You can use a reference to your list to make it mutable, put semicolons after each if statement and return the referenced list at the end:
let f list =
let list = ref list in
if cond1 then list := 1 :: !list;
if cond2 then list := 2 :: !list;
[...]
!list
;;
The given list will not be modified, there is just a new variable called list that shadows the original one within the function definition.

OCaml error: wrong type of expression in constructor

I have a function save that take standard input, which is used individually like this:
./try < input.txt (* save function is in try file *)
input.txt
2
3
10 29 23
22 14 9
and now i put the function into another file called path.ml which is a part of my interpreter. Now I have a problem in defining the type of Save function and this is because save function has type in_channel, but when i write
type term = Save of in_channel
ocamlc complain about the parameter in the command function.
How can i fix this error? This is the reason why in my last question posted on stackoverflow, I asked for the way to express a variable that accept any type. I understand the answers but actually it doesn't help much in make the code running.
This is my code:
(* Data types *)
open Printf
type term = Print_line_in_file of int*string
| Print of string
| Save of in_channel (* error here *)
;;
let input_line_opt ic =
try Some (input_line ic)
with End_of_file -> None
let nth_line n filename =
let ic = open_in filename in
let rec aux i =
match input_line_opt ic with
| Some line ->
if i = n then begin
close_in ic;
(line)
end else aux (succ i)
| None ->
close_in ic;
failwith "end of file reached"
in
aux 1
(* get all lines *)
let k = ref 1
let first = ref ""
let second = ref ""
let sequence = ref []
let append_item lst a = lst # [a]
let save () =
try
while true do
let line = input_line stdin in
if k = ref 1
then
begin
first := line;
incr k;
end else
if k = ref 2
then
begin
second := line;
incr k;
end else
begin
sequence := append_item !sequence line;
incr k;
end
done;
None
with
End_of_file -> None;;
let rec command term = match term with
| Print (n) -> print_endline n
| Print_line_in_file (n, f) -> print_endline (nth_line n f)
| Save () -> save ()
;;
EDIT
Error in code:
Save of in_channel:
Error: This pattern matches values of type unit
but a pattern was expected which matches values of type in_channel
Save of unit:
Error: This expression has type 'a option
but an expression was expected of type unit
There are many errors in this code, so it's hard to know where to start.
One problem is this: your save function has type unit -> 'a option. So it's not the same type as the other branches of your final match. The fix is straightforward: save should return (), not None. In OCaml these are completely different things.
The immediate problem seems to be that you have Save () in your match, but have declared Save as taking an input channel. Your current code doesn't have any way to pass the input channel to the save function, but if it did, you would want something more like this in your match:
| Save ch -> save ch
Errors like this suggest (to me) that you're not so familiar with OCaml's type system. It would probably save you a lot of trouble if you went through a tutorial of some kind before writing much more code. You can find tutorials at http://ocaml.org.