280 lines
5.4 KiB
OCaml
280 lines
5.4 KiB
OCaml
(*
|
|
COMPILE = ocamlc -o outfile infile.ml
|
|
|
|
UTOP = #use "filename.ml";;
|
|
*)
|
|
|
|
(*
|
|
Ocaml is thankfully garbage collected
|
|
|
|
Expressions must end with double semi colon
|
|
e.g. let name = "Bread";;
|
|
|
|
expressions can be evaluated to a value
|
|
|
|
ocaml is a statically typed and strongly typed language
|
|
meaning that at compile time the type of a variable will
|
|
be known. The compiler uses type inference to determine the
|
|
type of a variable that you dont need to specify;
|
|
|
|
e.g.
|
|
*)
|
|
|
|
(* string type *)
|
|
"Hello World";;
|
|
|
|
(* character type *)
|
|
'A';;
|
|
|
|
(* integer type *)
|
|
50;;
|
|
|
|
(* floating type *)
|
|
20.3;;
|
|
|
|
(*
|
|
OPERATIONS
|
|
|
|
you have basic operations such as
|
|
+, -, *, /, that works with integer types
|
|
|
|
to do these operations with floating point
|
|
numbers you need to use the following
|
|
|
|
+., -., *., /., notice the "." after the operator
|
|
|
|
-----------------------------------------------
|
|
|
|
MODULE does not use the % sign
|
|
|
|
use "mod" e.g.
|
|
|
|
3 mod 2;; - : int = 1 (* evaluates to 1 *)
|
|
|
|
----------------------------------------------
|
|
|
|
NOT uses the word "not" instead of "!" e.g.
|
|
|
|
not (1 < 2);; - : bool = false
|
|
*)
|
|
|
|
(*
|
|
COMPARATORS
|
|
|
|
standard and, or comparisons e.g.
|
|
|
|
a && b, a || b
|
|
|
|
you can use >, <, but the comparator uses a
|
|
single equal sign. e.g.
|
|
|
|
1. = 2.;; - : bool = false (* evaluates to false *)
|
|
|
|
-----------------------------------------------
|
|
|
|
NOT EQUALS
|
|
|
|
to check for inequality use "<>", e.g.
|
|
|
|
1. <> 2.;; - bool = true (* evaluates to true since 1. and 2. are not equal *)
|
|
*)
|
|
|
|
(*
|
|
STRING CONCATONATION
|
|
|
|
use the "^" (carrot operator) to concat strings e.g.
|
|
*)
|
|
"Braeden" ^ " " ^ "Sowinski"
|
|
|
|
(*
|
|
FUNCTIONS
|
|
|
|
define a function square that takes in a
|
|
parameter x and returns x * x
|
|
*)
|
|
let square x = x * x;;
|
|
square 5;;
|
|
|
|
(* evaluates to 6 *)
|
|
let x = 1 in x + 5;;
|
|
|
|
let add x y = x + y;;
|
|
|
|
(*
|
|
arrows are right associative
|
|
|
|
name : input -> input -> return type
|
|
val add : int -> int -> int = <fun>
|
|
|
|
so this can be translated to int -> (int -> int)
|
|
|
|
this means that every function essentially takes in 1 argument
|
|
that then returns another functoin that takes in another argument
|
|
*)
|
|
|
|
(* valid *)
|
|
add 1 2;;
|
|
|
|
(* valid *)
|
|
(add 1) 2;;
|
|
|
|
(* invalid *)
|
|
(*add (1 2);;*)
|
|
|
|
(*
|
|
Ocaml is functional and there are no loops
|
|
such as for or while,
|
|
|
|
all variables are immutable
|
|
*)
|
|
|
|
let x = 1;;
|
|
let x = 2;;
|
|
(*
|
|
x = 3;; (* cannot reassign, this evaluates as a comparison
|
|
therefore variables are immutable *)
|
|
*)
|
|
(*
|
|
RECURSION
|
|
|
|
recursion is related to mathematical induction,
|
|
you typically have a proposition, e.g. P, where we
|
|
know P(1) is true, and we assume P(k) is true
|
|
where we can proove that P(k + 1) is true
|
|
|
|
to declare a recursive function you need "rec"
|
|
*)
|
|
let rec factorial n = if n = 0 then 1 else n * factorial (n - 1);;
|
|
let r = (factorial 5);;
|
|
print_int r;;
|
|
print_endline "";;
|
|
|
|
(*
|
|
tail-recursive
|
|
|
|
a recursive function is tail-recursive if the recursive
|
|
call is the last thing we do, for example, factorial is not
|
|
tail-recursive, because we need to multiply n to the recursive call.
|
|
|
|
non tail-recursive functions are bad since there is potential to bloew
|
|
through the stack.
|
|
|
|
lets consider factorial 3 = 3 * fact 2
|
|
= 3 * (2 * fact 1)
|
|
= 3 * (2 * (1 * fact 0))
|
|
= 3 * (2 * 1)
|
|
= 3 * 2
|
|
= 6
|
|
|
|
we can see that this is not tail recursive as we need to store a value for
|
|
each part of the iteration, we can solve this by rewriting the function a little
|
|
using an accumulator
|
|
*)
|
|
let rec fact n acc = if n = 0 then acc else fact (n - 1) (n * acc);;
|
|
|
|
(* we can have primes, e.g. function f, and function f prime or f' *)
|
|
|
|
let factorial' n = fact n 1;;
|
|
let r = (factorial 5);;
|
|
print_int r;;
|
|
print_endline "";;
|
|
|
|
let factorial' = fact 1;;
|
|
|
|
(*
|
|
consider the tail-recursive version of factorial, fact'
|
|
|
|
the signature is fact' n acc
|
|
|
|
fact' 1 3 = fact' 3 2
|
|
= fact' 6 1
|
|
= fact' 6 0
|
|
|
|
as you can see, the stack would not grow
|
|
|
|
lets combine the functoins into a single one
|
|
with nesting
|
|
*)
|
|
(* final tail-recursive version *)
|
|
let fact n =
|
|
let rec fact' acc i =
|
|
if i = 0 then acc
|
|
else fact' (i * acc) (i - 1)
|
|
in
|
|
fact' 1 n;; (* automatically sets the accumulator to 1 *)
|
|
|
|
let r = fact 5;;
|
|
print_int r;;
|
|
print_endline "";;
|
|
|
|
(* example of a documentation comment *)
|
|
|
|
(** [gcd a b] returns the greatest common divisor of [a] and [b]
|
|
* Requires:[a > 0] and [b > 0]
|
|
*)
|
|
let rec gcd a b =
|
|
if a mod b = 0 then b
|
|
else gcd b (a mod b);;
|
|
(*
|
|
let r = gcd 12 18;;
|
|
print_int r;;
|
|
print_endline "";; *)
|
|
|
|
let rec fib n =
|
|
if n = 0 then 0
|
|
else if n = 1 then 1
|
|
else fib (n - 1) + fib (n - 2);;
|
|
|
|
let r = fib 10;;
|
|
print_int r;;
|
|
print_endline "";;
|
|
|
|
(* tail-recursive version *)
|
|
let rec fib n =
|
|
let rec fib' i a b =
|
|
if i = n then a
|
|
else fib' (i + 1) b (a + b)
|
|
in
|
|
fib' 0 0 1;;
|
|
|
|
let r = fib 10;;
|
|
print_int r;;
|
|
print_endline "";;
|
|
|
|
(*
|
|
MUTALLY-RECURSIVE FUNCTION
|
|
*)
|
|
let rec even n =
|
|
if n = 0 then true
|
|
else odd (n - 1)
|
|
and odd n =
|
|
if n = 0 then false
|
|
else even (n - 1);;
|
|
|
|
(*
|
|
useful stuff
|
|
|
|
float_of_int 4
|
|
int_of_string "123"
|
|
*)
|
|
|
|
let square_root x =
|
|
let good_enough y = abs_float (x -. y *. y) < 0.00000000001 in
|
|
let rec aux y =
|
|
if good_enough y then y
|
|
else aux (0.5 *. (y +. x /. y))
|
|
in
|
|
aux 1.;;
|
|
|
|
print_float (square_root 2.);;
|
|
print_endline "";;
|
|
|
|
(*
|
|
Consider this
|
|
|
|
create an exponential function
|
|
where it calculates e^x
|
|
|
|
using recursion
|
|
*)
|