Syntax error when Calling function inside function in Ocaml - ocaml

I am getting a Syntax error when calling the function f and g inside lp and assigning them to y and z
let lp m =
let y = f m in
let z = g y (List.length y) m;
Here's my full code:
open Printf
open Format
let regraUm m = m/2
let regraDois m = ((m / 10) mod 10) * (m mod 10)
let regraTres m = 42
let f m =
let list = ref [] in
if ((m mod 2) = 0) then list := 1::!list;
if ((m mod 3) = 0) || ((m mod 4) = 0) then list := 2::!list;
if ((m mod 5) = 0) then list := 3::!list;
!list
let g list len m =
let res = ref [] in
for i = 0 to (len-1) do
let regra = List.nth list i in
if (regra = 1) then res := (m - (regraUm m))::!res;
if (regra = 2) || ((m mod 4) = 0) then res := (m - (regraDois m))::!res;
if (regra = 3) then res := (m - (regraTres m))::!res;
done;
!res
let lp m =
let y = f m in
let z = g y (List.length y) m;
Syntax Error:
ocamlopt regras.ml -o r
File "regras.ml", line 33, characters 4-4:
Error: Syntax error
f and g work properly when used outside of a function.

A let binding need some expression to be attached after an in, which in your case doesn't exist. In this case your code would work either adding z as expression or removing the binding leaving just the expression.
let lp m =
let y = f m in
let z = g y (List.length y) m in
z
Or this
let lp m =
let y = f m in
g y (List.length y) m

Related

Evaluation order of let-in expressions with tuples

My old notes on ML say that
let (๐‘ฃโ‚, โ€ฆ , ๐‘ฃโ‚™) = (๐‘กโ‚, โ€ฆ , ๐‘กโ‚™) in ๐‘กโ€ฒ
is a syntactic sugar for
(ฮป ๐‘ฃโ‚™. โ€ฆ (ฮป ๐‘ฃโ‚. ๐‘กโ€ฒ)๐‘กโ‚ โ€ฆ )๐‘กโ‚™
and that
let (๐‘ฃโ‚, ๐‘ฃโ‚‚) = ๐‘ก ๐‘กโ€ฒ in ๐‘กโ€ณ
is equivalent to
let ๐‘ฃ = ๐‘ก ๐‘กโ€ฒ in
let ๐‘ฃโ‚‚ = snd ๐‘ฃ in
let ๐‘ฃโ‚ = fst ๐‘ฃ in
๐‘กโ€ณ
where
each ๐‘ฃ (with or without a subscript) stands for a variable,
each ๐‘ก (with or without a sub- or a superscript) stands for a term, and
fst and snd deliver the first and second component of a pair, respectively.
I'm wondering whether I got the evaluation order right because I didn't note the original reference. Could anyone ((confirm or reject) and (supply a reference))?
It shouldn't matter whether it's:
let ๐‘ฃ = ๐‘ก ๐‘กโ€ฒ in
let ๐‘ฃโ‚‚ = snd ๐‘ฃ in
let ๐‘ฃโ‚ = fst ๐‘ฃ in
๐‘กโ€ณ
Or:
let ๐‘ฃ = ๐‘ก ๐‘กโ€ฒ in
let ๐‘ฃโ‚ = fst ๐‘ฃ in
let ๐‘ฃโ‚‚ = snd ๐‘ฃ in
๐‘กโ€ณ
Since neither fst nor snd have any side-effects. Side-effects may exist in the evaluation of ๐‘ก ๐‘กโ€ฒ but that's done before the let binding takes place.
Additionally, as in:
let (๐‘ฃโ‚, ๐‘ฃโ‚‚) = ๐‘ก ๐‘กโ€ฒ in ๐‘กโ€ณ
Neither ๐‘ฃโ‚ nor ๐‘ฃโ‚‚ is reliant on the value bound to the other to determine its value, so the order in which they're bound is again seemingly irrelevant.
All of that said, there may be an authoritative answer from those with deeper knowledge of the SML standard or the inner workings of OCaml's implementation. I simply am uncertain of how knowing it will provide any practical benefit.
Practical test
As a practical test, running some code where we bind a tuple of multiple expressions with side-effects to observe order of evaluation. In OCaml (5.0.0) the order of evaluation is observed to be right-to-left. We observe tthe same when it comes to evaluating the contents of a list where those expressions have side-effects as well.
# let f () = print_endline "f"; 1 in
let g () = print_endline "g"; 2 in
let h () = print_endline "h"; 3 in
let (a, b, c) = (f (), g (), h ()) in a + b + c;;
h
g
f
- : int = 6
# let f () = print_endline "f"; 1 in
let g () = print_endline "g"; 2 in
let h () = print_endline "h"; 3 in
let (c, b, a) = (h (), g(), f ()) in a + b + c;;
f
g
h
- : int = 6
# let f _ = print_endline "f"; 1 in
let g () = print_endline "g"; 2 in
let h () = print_endline "h"; 3 in
let a () = print_endline "a" in
let b () = print_endline "b" in
let (c, d, e) = (f [a (); b ()], g (), h ()) in
c + d + e;;
h
g
b
a
f
- : int = 6
In SML (SML/NJ v110.99.3) we observe the opposite: left-to-right evaluation of expressions.
- let
= fun f() = (print "f\n"; 1)
= fun g() = (print "g\n"; 2)
= fun h() = (print "h\n"; 3)
= val (a, b, c) = (f(), g(), h())
= in
= a + b + c
= end;
f
g
h
val it = 6 : int
- let
= fun f() = (print "f\n"; 1)
= fun g() = (print "g\n"; 2)
= fun h() = (print "h\n"; 3)
= val (c, b, a) = (h(), g(), f())
= in
= a + b + c
= end;
h
g
f
val it = 6 : int
- let
= fun f _ = (print "f\n"; 1)
= fun g() = (print "g\n"; 2)
= fun h() = (print "h\n"; 3)
= fun a() = print "a\n"
= fun b() = print "b\n"
= val (c, d, e) = (f [a(), b()], g(), h())
= in
= c + d + e
= end;
a
b
f
g
h
val it = 6 : int
Be aware that, in OCaml, due to the (relaxation of the) value restriction, let a = b in c is not equivalent to (fun a -> c)b. A counterexample is
# let id = fun x -> x in id 5, id 'a';;
- : int * char = (5, 'a')
# (fun id -> id 5, id 'a')(fun x -> x)
Error: This expression has type char but an expression was expected of type int
#
This means that they are semantically not the same construction (the let ... = ... in ... is strictly more general that the other).
This happens because, in general, the type system of OCaml doesn't allow types of the form (โˆ€ฮฑ.ฮฑโ†’ฮฑ) โ†’ int * char (because allowing them would make typing undecidable, which is not very practical), which would be the type of fun id -> id 5, id 'a'. Instead, it resorts to having the less general type โˆ€ฮฑ.(ฮฑโ†’ฮฑ) โ†’ ฮฑ * ฮฑ, which doesn't make it typecheck, because you can't unify both ฮฑ with char and with int.

Syntax Error when calling Recursive Function inside a Recursive Function in Ocaml

The compiler returns a Syntax error when using the command in
xyz aux
if((match4242 aux) = 0) then main (!list) else 1
Here's my full code.
open Printf
open Format
let regraUm m = m/2
let regraDois m = ((m / 10) mod 10) * (m mod 10)
let regraTres m = 42
let match4242 list =
let a = ref 0 in
let rec match42 list =
match list with
|[]->[]
|m::body->
begin
if (m = 42) then a := 1;
match42 body
end
in match42 list;
!a
let rec main aux =
let list = ref [] in
let rec xyz aux =
let () = List.iter (fun x -> printf "%d " x) aux in
match aux with
|[]->[]
|m::body ->
begin
if ((m mod 2) = 0) then list := (m - (regraUm m))::!list;
if ((m mod 3) = 0) || ((m mod 4) = 0) then
if (regraDois m <> 0) then
list := (m - (regraDois m)) ::!list;
if ((m mod 5) = 0) then list := (m - (regraTres m))::!list;
xyz body
end
in xyz aux
if((match4242 aux) = 0) then main (!list) else 1
The program checks if 42 is inside the list, if not then it calls itself again following a set of rules of division, subtraction, etc.
I don't know if this last info is helpful to debug this piece of code.
These two lines:
xyz aux
if ((match4242 aux) = 0) then main (!list) else 1
Represent a single expression, since they aren't separated by ;. But indeed you can't have an if expression in this position (function argument) unless you parenthesize it.
Most likely you want ; after aux here.

increasing sum of the elements of a list

How to compute the sum of each element of a list multiplied by it's index position in OCaml? example: for [4;7;9] the result is 45 (4x1 + 7x2 + 9x3 = 45). the only authorized functions are List.hd, List.tl et List.length.
I can do it in the other direction with this code:
let rec sum l =
let n = (List.length l) + 1 in
if l = [] then 0 else
((List.hd l)*(n-1))+ (sum(List.tl l)) ;;
sum [4;7;9];;
- : int = 35 (4x3 + 7x2 + 9x1 = 35)
But the expected result is 45 (4x1 + 7x2 + 9x3 = 45).
thank you for your help.
Personally, I'd probably do something like this..
let rec new_sum l n =
match l with
| [] -> 0
| head::tail -> (head * n) + new_sum tail (n+1)
let sum l =
new_sum l 1;;
sum [4;7;9]
...if you don't like the guards for pattern matching, and prefer List.hd, List.tl, List.length then you could use...
let rec new_sum l n =
if (List.length l == 0) then 0
else ((List.hd l) * n) + new_sum (List.tl l) (n+1)
let sum l =
new_sum l 1;;
sum [4;7;9];

Getting max value from a list in SML

I'm currently studying SML and I'm having a hard time understanding the code below
fun good_max (xs : int list) =
if null xs
then 0
else if null (tl xs)
then hd xs
else
(* for style, could also use a let-binding for (hd xs) *)
let val tl_ans = good_max(tl xs)
in
if hd xs > tl_ans
then hd xs
else tl_ans
end
hd xs is of type int and tl_ans, I think is of type list.
Why does this code work? How does the system evaluate the recursion?
It would be great if you could use xs = [3, 4, 5] to show me how this works.
Let me first rewrite this code to an equivalent but more readable version:
fun max(x,y) = if x > y then x else y
fun goodMax(nil) = 0
| goodMax(x::nil) = x
| goodMax(x::xs) = let val y = goodMax(xs) in max(x,y) end
Now we can consider how evaluation of goodMax([3,4,5]) proceeds: conceptually, it will be reduced to an answer by repeatedly substituting the respective branch of the function definition(s):
goodMax([3,4,5])
= goodMax(3::[4,5])
= let val y = goodMax([4,5]) in max(3, y) end
= let val y = goodMax(4::[5]) in max(3, y) end
= let val y = (let val y' = goodMax([5]) in max(4, y') end) in max(3, y) end
= let val y = (let val y' = goodMax(5::nil) in max(4, y') end) in max(3, y) end
= let val y = (let val y' = 5 in max(4, y') end) in max(3, y) end
= let val y = max(4, 5) in max(3, y) end
= let val y = (if 4 > 5 then 4 else 5) in max(3, y) end
= let val y = 5 in max(3, y) end
= max(3, 5)
= if 3 > 5 then 3 else 5
= 5
I have renamed the y in the inner invocation to y' for clarity.

Why this code works in interactive but fails when compiled?

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