Reputation: 10607
I'm a complete newbie in OCaml and trying to create a simple console program.
(*let k = read_int()
let l = read_int()
let m = read_int()
let n = read_int()
let d = read_int()*)
let k = 5
let l = 2
let m = 3
let n = 4
let d = 42
let rec total: int -> int -> int = fun i acc ->
if i > d then
acc
else
if (i mod k) == 0 || (i mod l) == 0 || (i mod m) == 0 || (i mod n) == 0 then
total (i + 1) (acc + 1)
else
total (i + 1) acc;
print_int (total 1 0)
But if I try to compile it, it fails:
PS C:\Users\user> ocamlc -g .\a148.ml
File ".\a148.ml", line 14, characters 2-180:
Warning S: this expression should have type unit.
File ".\a148.ml", line 22, characters 0-21:
Error: This expression has type unit but is here used with type int
So, looks like if
expression cannot return value here (why?). I've added let
binding
let k = 5
let l = 2
let m = 3
let n = 4
let d = 42
let rec total: int -> int -> int = fun i acc ->
let x' = if i > d then
acc
else
if (i mod k) == 0 || (i mod l) == 0 || (i mod m) == 0 || (i mod n) == 0 then
total (i + 1) (acc + 1)
else
total (i + 1) acc;
x'
print_int (total 1 0)
and it works, but raises another error:
File ".\a148.ml", line 23, characters 0-0:
Error: Syntax error
Line 23 is the next to print_int
statement and empty, so it seems like compiler wants something else from me, but I don't know what.
UPD: ok, the working code:
let k = 5 in
let l = 2 in
let m = 3 in
let n = 4 in
let d = 42 in
let rec total i acc =
if i > d then
acc
else
if (i mod k) == 0 || (i mod l) == 0 || (i mod m) == 0 || (i mod n) == 0 then
total (i + 1) (acc + 1)
else
total (i + 1) acc
in let x = total 1 0 in
print_int x;
Upvotes: 2
Views: 216
Reputation: 41290
The problem is the misuse of semicolon (;
).
Semicolon intends to be the sequence composition of two expressions. S1 ; S2
means that the compiler expects S1
to be unit
type, computes S1
and S2
in that order and returns the result of S2
.
Here you mistakenly use ;
, so OCaml expects the second if...then...else
to return unit
and wants you to provide one more expression. Removing ;
and adding necessary in
(s) should make the function compile:
let k = 5 in
let l = 2 in
let m = 3 in
let n = 4 in
let d = 42 in
let rec total: int -> int -> int = fun i acc ->
if i > d then
acc
else
if (i mod k) == 0 || (i mod l) == 0 || (i mod m) == 0 || (i mod n) == 0 then
total (i + 1) (acc + 1)
else
total (i + 1) acc
Regarding your second function, you should replace ;
by in
to indicate that x'
is used to compute the return value.
BTW, your total
function looks weird since you use lambda expression in the function body. Explicit declaration is more readable:
let rec total i acc =
if i > d then
acc
else if i mod k = 0 || i mod l = 0 || i mod m = 0 || i mod n = 0 then
total (i + 1) (acc + 1)
else
total (i + 1) acc
I have also changed reference equality (==)
to structural equality (=)
though there is no difference among them in integer.
Upvotes: 2