How to pass values of variables in OCaml - if-statement

In imperative languages I can easily write something like this:
if(x > y) {
int t = x;
x = y;
y = t;
}
The values of the variables are getting passed to another. However if I try writing this in Ocaml, the compiler sees this as a comparison, so it turns out to be bool:
if x > y then
let t = x in
let x = y in
let y = b in
How can I pass the value of variables to another?

Rather than variables, OCaml has named values. If you want to shuffle the names of some values, you can write:
let x, y =
if x > y then y, x
else x, y
in

If you want to mirror the imperative code exactly you would write:
# let x = ref 2;;
val x : int ref = {contents = 2}
# let y = ref 1;;
val y : int ref = {contents = 1}
# let swap_if x y = if !x > !y then let t = !x in x := !y; y := t;;
val swap_if : 'a ref -> 'a ref -> unit = <fun>
# swap_if x y;;
- : unit = ()
# !x, !y;;
- : int * int = (1, 2)
Writing it functional you would do
let (x, y) = if x > y then (y, x) else (x, y)
or
let (x, y) = (min x y, max x y)
But note that this will not change x and y. Rather it creates new variables x and y that shadow the previous bindings.

Related

OCaml function comparing numbers

I am trying to write a function that takes 3 numbers, x y z. If x is equal to y, then it should return z. Otherwise, return x. I am having trouble figuring out why my attempt always returns z, even if x!=y. Any help would be appreciated I am still new to OCaml.
let test x y z =
match x with
| y when x = y -> z
| _ -> x
Your code doesn't compare x to y, it uses the pattern y to match against x. This always succeeds and binds y to the value of x. That is, you're creating a new local variable y that has the same value as x.
To fix your code, you could do this:
let test x y z =
match x with
| _ when x = y -> z
| _ -> x
But that seems a bit silly when you could just do:
let test x y z =
if x = y then z else x

Decrypting return of function in OCaml

I'am trying to decrypt the return of calc function below but i'am very confused.
I have the f function that takes 3 ints and returns an int.
The calc fuction i think should return val calc : int -> int = <fun> because f has to take 3 ints, i'am giving it x and y so now it needs one more to return another int, the final result. Why it this logic not correct?
I can't make any sense of the actual output, specially with the polymorfic values when i forced parameters in f to be integers.
# let f (x : int) (y : int) (z : int) = x + y + z;;
val f : int -> int -> int -> int = <fun>
# let calc x y f = f x y;;
val calc : 'a -> 'b -> ('a -> 'b -> 'c) -> 'c = <fun>
In the expression let calc x y f = f x y;;, f is a locally-bound variable (calc binds x, y and then f) rather than the function you have defined before.
If you had written let calc x y = f x y;; then you'd have the expected result.
The function calc contains no reference to the functionf. There is an argument named f be it could be named g without changing anything: let calc x y g = g x y. If you want to use the function f you have defined above and not any function of the right type, you must not pass f as an argument, you should rewrite calc like this:
let f x y z = x + y + z
let calc x y = f x y
and then calc will have the type int -> int -> (int -> int) which is more commonly written as int -> int -> int -> int.

OCaml how to manipulate tuples?

Let's say I have a tuple:
let x = (1,3)
I want to add 1 to only the first value of the tuple. How would I do that?
You use pattern matching to deconstruct the tuple and then construct the updated one:
let (x1, x2) = x in (x1 + 1, x2)
Patterm matching is a typical idiom. Another way would be with fst and snd:
# let x = (1,3);;
val x : int * int = (1, 3)
# let y = (fst x + 1, snd x);;
val y : int * int = (2, 3)

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.

Mutable Types in OCaml

I am writing a function that swaps the contents of two reference calls.
let swap (x : a ref) (y :'a ref) : unit =
where
type 'a ref = {mutable contents : 'a}
I do not know what approach to take in order to solve this. Do I use pattern matching?
This is my test case
let test () : bool =
let r1 = { contents = 5 } in
let r2 = { contents = 6 } in
let _ = swap r1 r2 in
(6, 5) = (r1.contents, r2.contents)
;;
run_test "Swap different" test
Does this work?
let swap x y =
let z = !x in
x := !y;
y := z
Note that := and ! are just normal functions like so:
let (:=) r x = r.contents <- x
let (!) {contents} = contents
If you want to use own your type definition then you can do:
let swap' x y =
let z = x.contents in
x.contents <- y.contents;
y.contents <- z
Finally, if you're using batteries then you can just use BatRef.swap as defined here: http://ocaml-batteries-team.github.com/batteries-included/hdoc2/BatRef.html