Trouble breaking out of a loop - ocaml

I'm starting to learn OCaml, and I don't understand why this loops indefinitely:
let x = true in
while x do
print_string "test";
x = false;
done;;
What am I missing?

One reason to study OCaml is to learn how to compute with immutable values. Here's a version that doesn't depend on a mutable variable:
let rec loop x =
if x then
begin
print_string "test";
loop false
end
in
loop true
The trick is to reimagine the mutable values as function parameters, which allows them to have different values different times.

It's because OCaml let bindings are immutable. This exact issue is discussed in detail in the ocaml.org tutorial. Use a ref instead, and set and get the value it holds using ! and :=:
let x = ref true in
while !x do
print_string "test";
x := false
done;;

It's best to run ocaml with warnings and strict sequence on to detect problems. e.g.
$ ocaml -strict-sequence -w A
OCaml version 4.01.0
# let x = true in
while x do
print_string "test";
x = false;
done;;
Error: This expression has type bool but an expression was expected of type
unit
This shows the problem: x = false is testing whether x is false or not, not doing an assignment.

Related

OCaml initializing list in loop for

I am a beginner with OCaml. I would like to skip the first element of my list.
Here is my list:
let l = [1;2;3;4;5;6;7;2;1];;
I want to use this in my FOR:
let l = List.tl l;
here is my full code:
let l = [1;2;3;4;5;6;7;2;1];;
let n = 1;;
let counter = ref 0;;
for i = 0 to (List.length l) do
if List.hd l = n then counter := !counter + 1;
print_int(!counter);
print_string("\n");
let l = List.tl l
done;;
But I have errors in the DONE and it says syntax error.
Can anyone help me please?
Your problem is that let always requires a matching in. The full expression looks like this:
let var = expr1 in expr2
Since you're missing the in part, you get a syntax error.
However, the deeper problem is that you're trying to modify the value of l. The way you have defined l, it's immutable. You can't change its value. If you want to be able to change its value you can define it as a reference, as you have done for counter.
(There is another form of let used at the top level of a module. This form doesn't have a matching in. But your code isn't defining a top-level name, so this is not relevant.)

Ocaml if-then-else Syntax Error

Why is this Ocaml statement giving me a syntax error?
let a = 0;; if a = 0 then let b = 0;;
Do if then else statements always have to return a value?
EDIT: Here is the code I am struggling with. I want to apply this function over a list with the map function. The function is supposed to look at each word in the list wordlist and add to the stringmap. If it has already been added to the string map then add 1 to its password.
module StringMap = Map.Make(String)
let wordcount = StringMap.empty
let findword testword =
let wordcount = (if (StringMap.mem testword wordcount)
then (StringMap.add testword ((StringMap.find testword wordcount)+1) wordcount)
else (StringMap.add testword 1 wordcount))
List.map findword wordlist
You can only have an if then without else if the then expression evaluates to unit () Otherwise, the expression will not type check. An if without an else is equivalent to writing if x then y else () which can only type check if y is unit.
Check this out for a reference.
(Terminology note: there are no statements in OCaml because everything is an expression, so the term "if statement" doesn't quite apply. I still understood what you meant, but I thought this was worth noting)
Yes, if is an expression in OCaml, not a statement. The best way to look at it is that there are no statements in OCaml. Everything is an expression. (Admittedly there are expressions that return (), which are similar to statements.)
You can only have if b then e if the type of e is unit (i.e., if it returns ()).
Note also that you can't just say let v = e, except at the top level of a module. At the top level it defines a global name in the module. In other cases you need to say let v = e1 in e2; the let defines a local symbol v for use in the expression e2.
One answer to the let b = problem - it works like this:
let a = 0
let b = if a = 0 then 0 else 1
(* or whatever value you need in the else branch *)
And then the Map problem: the manual says Map is applicative - that means Stringmap.add returns a new map. You must use a ref to store your map - see this ocaml toplevel protocol:
# module StringMap = Map.Make(String);;
# let mymap = ref StringMap.empty ;;
val mymap : '_a StringMap.t ref = {contents = <abstr>}
# mymap := StringMap.add "high" 1 !mymap;;
- : unit = ()
# StringMap.mem "high" !mymap;;
- : bool = true
# StringMap.mem "nono" !mymap;;
- : bool = false
# StringMap.find "high" !mymap;;
- : int = 1
# StringMap.find "nono" !mymap;;
Exception: Not_found.

Evaluating List to Weak Head Normal Form

Given the following list from 1 to 100:
> let x = [1..100]
I run sprint x to observe its unevaluated value.
> :sprint x
x = _
Then, I ran seq to evaluate it to Weak Head Normal Form:
> seq x ()
()
But re-running sprint x shows (what I think) is the same value.
> :sprint x
x = _
Why is that?
I think this bheklilr's comment should be marked as the answer:
What is the type of x? If it's (Num a, Enum a) => [a] then this won't work as expected. Try let x = [1..100] :: [Int]. In reality, when you print x with the more general type GHCi specializes it to Integer to do the printing. This means that the values you see printed are not actually stored back in x's thunk. Using a concrete type avoids this problem.
With the additional note from David Young that this problem won't occur on GHCi versions earlier than 7.8, when the monomorphism restriction was enabled.

Using length function in OCaml

I'm begining my learning of OCaml and I have been quite stuck on a simple problem.
I'm trying to count with a simple loop the number of letters that I have in a file of 6 lines.
Here's my code :
let fi = open_in "example";;
let string = "";;
let nb_carac = 0;;
for i = 0 to 6 do
string = input_line fi;
nb_carac = (nb_carac + String.length(string));
done;;
Problem is, it doesn't seem to count anything and reaches directly to EOF.
I get the following error message:
Warning 10: this expression should have type unit.
Warning 10: this expression should have type unit.
Exception: End_of_file.
I don't really get it. I have tried each line individually and they all worked. What am i doing wrong?
Thanks!
OCaml does not have mutable variables. You should use tail recursion or references. Read any basic OCaml textbook or tutorial.
Both lines:
string = input_line fi;
nb_carac = (nb_carac + String.length(string));
are understood as useless equality tests (this explains the warning you are getting).
Perhaps you want:
(* shameful *)
let string = ref "";;
let nb_carac = ref 0;;
then e.g.
(* shameful *)
string := input_line fi;
nb_carac := !nb_carac + String.length(!string);
but you should get a very bad grade if you code so imperatively in a functional language like OCaml.
As a rule of thumb, avoid mutating data when coding in OCaml. Of course there are important exceptions to this rule.
The correct solution to your exercise is to use tail recursive functions which do not mutate any data. Look at OCaml standard library stdlib/list.ml for some inspiration.
Probably a better solution to your exercise starts with
let count_lines_and_characters fil = (* incomplete code, fill the ... *)
let rec ....
in ....
;;
Of course you should fill the ....

How to use List.nth inside a function

I am new to OCaml. I am trying to use List.nth just like List.length but it keeps giving me a syntax error or complains about not matching the interface defined in another file. Everything seems to work fine if I comment out using List.nth
Thanks
It's hard to help unless you show the code that's not working. Here is a session that uses List.nth:
$ ocaml
OCaml version 4.00.0
# let x = [3;5;7;9];;
val x : int list = [3; 5; 7; 9]
# List.nth x 2;;
- : int = 7
#
Here's a session that defines a function that uses List.nth. (There's nothing special about this.)
# let name_of_day k =
List.nth ["Mon";"Tue";"Wed";"Thu";"Fri";"Sat";"Sun"] k;;
val name_of_day : int -> string = <fun>
# name_of_day 3;;
- : string = "Thu"
# 
(As a side comment: using List.nth is often inappropriate. It takes time proportional to n to find the nth element of a list. People just starting with OCaml often think of it like accessing an array--i.e., constant time--but it's not.)