TITLE::OCaml 101 OCaml 101 by Samuel Tesla ---- OCaml ---- What is it? ---- Functional ---- Interpreted ---- Compiled ---- Byte code ---- Native code ---- Statically typed ---- [[EM:WHAT?:EM]] ---- Omaha [[EM:Dynamic:EM]] Language User Group ---- So what's up with the static language? ---- Static typing is cool ---- It protects you from this ---- [[PRE:NoMethodError: undefined method 'frob' for foo:SomeClass:PRE]] [[PRE:ArgumentError: wrong number of arguments (2 for 1) :PRE]] ---- For [[EM:free:EM]] ---- Most static languages look like this ---- [[PRE:void StreamEncoder:: doWrite(const uchar c) { char ch = (char) c; _out.put(ch); }:PRE]] ---- That is to say they look ---- [[EM:UGLY:EM]] ---- Wouldn't it look better like this? ---- [[PRE:let do_write c = Out.put c:PRE]] ---- That's OCaml ---- Now for some code ---- From [[The Manual|http://caml.inria.fr/pub/docs/manual-ocaml/index.html]] ---- [[PRE:# 1+2*3;; - : int = 7:PRE]] ---- [[PRE:# let pi = 4.0 *. atan 1.0;; val pi : float = 3.14159265358979312:PRE]] ---- [[PRE:# 1.0 * 2;; This expression has type float but is here used with type int:PRE]] ---- [[PRE:# let square x = x *. x;; val square : float -> float = :PRE]] ---- It figured out the type ---- All on its own ---- [[PRE:# square(sin pi) +. square(cos pi);; - : float = 1.:PRE]] ---- [[PRE:# let rec fib n = if n < 2 then 1 else fib(n-1) + fib(n-2);; val fib : int -> int = :PRE]] ---- [[PRE:# fib 10;; - : int = 89:PRE]] ---- [[PRE:# (1 < 2) = false;; - : bool = false:PRE]] ---- [[PRE:# 'a';; - : char = 'a':PRE]] ---- [[PRE:# "Hello world";; - : string = "Hello world":PRE]] ---- [[PRE:# (1, 1.0, "one");; - : int * float * string = (1, 1., "one"):PRE]] ---- [[PRE:# let l = ["foo"; "bar"; "baz"];; val l : string list = ["foo"; "bar"; "baz"]:PRE]] ---- [[PRE:# "quux" :: l;; - : string list = ["quux"; "foo"; "bar"; "baz"]:PRE]] ---- [[PRE:# let rec sort lst = match lst with [] -> [] | head :: tail -> insert head (sort tail) and insert elt lst = match lst with [] -> [elt] | head :: tail -> if elt <= head then elt :: lst else head :: insert elt tail ;; val sort : 'a list -> 'a list = val insert : 'a -> 'a list -> 'a list = :PRE]] ---- [[PRE:# sort l;; - : string list = ["bar"; "baz"; "foo"] # sort [6;2;5;3];; - : int list = [2; 3; 5; 6] # sort [3.14; 2.718];; - : float list = [2.718; 3.14]:PRE]] ---- [[PRE:# let deriv f dx = fun x -> (f(x +. dx) -. f(x)) /. dx;; val deriv : (float -> float) -> float -> float -> float = :PRE]] ---- [[PRE:# let sin' = deriv sin 1e-6;; val sin' : float -> float = :PRE]] ---- [[PRE:# sin' pi;; - : float = -1.00000000013961143:PRE]] ---- [[PRE:# let rec map f l = match l with [] -> [] | hd :: tl -> f hd :: map f tl;; val map : ('a -> 'b) -> 'a list -> 'b list = :PRE]] ---- [[PRE:List.map:PRE]] ---- [[PRE:# type ratio = {num: int; denum: int};; type ratio = { num : int; denum : int; }:PRE]] ---- [[PRE:# let add_ratio r1 r2 = {num = r1.num * r2.denum + r2.num * r1.denum; denum = r1.denum * r2.denum};; val add_ratio : ratio -> ratio -> ratio = :PRE]] ---- [[PRE:# add_ratio {num=1; denum=3} {num=2; denum=5};; - : ratio = {num = 11; denum = 15}:PRE]] ---- [[PRE:# type number = Int of int | Float of float | Error;; type number = Int of int | Float of float | Error:PRE]] ---- [[PRE:# let add_num n1 n2 = match (n1, n2) with (Int i1, Int i2) -> (* Check for overflow of integer addition *) if sign_int i1 = sign_int i2 && sign_int(i1 + i2) <> sign_int i1 then Float(float i1 +. float i2) else Int(i1 + i2) | (Int i1, Float f2) -> Float(float i1 +. f2) | (Float f1, Int i2) -> Float(f1 +. float i2) | (Float f1, Float f2) -> Float(f1 +. f2) | (Error, _) -> Error | (_, Error) -> Error;;:PRE]] ---- [[PRE:# add_num (Int 123) (Float 3.14159);; - : number = Float 126.14159:PRE]] ---- [[PRE:# type 'a btree = Empty | Node of 'a * 'a btree * 'a btree;; type 'a btree = Empty | Node of 'a * 'a btree * 'a btree:PRE]] ---- [[PRE:# let rec member x btree = match btree with Empty -> false | Node(y, left, right) -> if x = y then true else if x < y then member x left else member x right;; val member : 'a -> 'a btree -> bool = :PRE]] ---- [[PRE:# let rec insert x btree = match btree with Empty -> Node(x, Empty, Empty) | Node(y, left, right) -> if x <= y then Node(y, insert x left, right) else Node(y, left, insert x right);; val insert : 'a -> 'a btree -> 'a btree = :PRE]] ---- OCaml also has imperative features ---- reference variables ---- arrays ---- for loops while loops ---- exceptions ---- objects ---- You can write programs ---- You can write libraries ---- You can use C libraries from OCaml ---- You can use OCaml libraries from C ---- All the joy of functional programming ---- All the speed of native code ---- [[OCaml|http://caml.inria.fr/]]