(* 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 = 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 *)