A way of expressing a program's purpose
Don't really care how
Consider the iterative:
(* iterative.rb *)
arr = [1,2,3]
res = []
for i in arr
if i % 2 == 0
res.push(i)
end
end
res
Tells you what to do
Series of steps to achieve your goal
Consider the declarative:
(* declare.rb *)
arr = [1,2,3] in
arr.filter{|x| x%2==0}
Tells you what you want
Does not care how, just the end result
Focus on what you want, and don't worry about the specifics
Focus on what you want, and don't worry about the specifics
Function: input to output
Combine functions to get what you want
Either recursively or combination of functions
(* let.ml *)
let x = e1 in e2
Let expressions are expressions
Expressions have a type
(* let-type.ml *)
(let x = e1:t1 in e2:t2):t2
Can be nested
(* let-nest.ml *)
let x = 3 in let y = 4 in x + y
Can be used for local variables
(* let-vars.ml *)
let area r =
let pi = 3.14 in
pi *. r *. r
Variables will be shadowed
(* let-shadowing.ml *)
let x = 3 in let x = 5 in x + 4
Lists are the basic data structure in OCaml
Lists are the basic data structure in OCaml
(* lists.ml *)
[1;2;3;4;5]
List Creation
(* lists-1.ml *)
e1::e2::[]
Lists are the basic data structure in OCaml
(* lists-1.ml *)
e1::e2::[]
Have type list
When evaluating, go right to left
Can deconstruct lists
(* match-nest.ml *)
let x = [1;2;3] in match x with
|[] -> true
|h::t -> false
Match looks at patterns of structure
Match looks at patterns of structure
Common Patterns
(* match-patterns.ml *)
let empty x = in match x with
|[] -> true (* empty *)
|a::[] -> false (* list of size 1 *)
|h::t -> false (* list at least size 1 *)
|_ -> false (* wildcard *)
Variables are bound on order
Last item is a list
Match looks at patterns of structure
Can be put as argument
(* match-function.ml *)
let car (h::_) = h;;
let cdr (_::t) = t;;
Match looks at patterns of structure
Can be Polymorphic
(* match-polymorphic.ml *)
let car lst = match lst with
[] -> []
h::_ -> h;;
(* lst has type 'a list *)
let rec sum lst = match lst with
[]-> 0
|h::t -> h + sum t;;
(* h has type int list *)
Used commonly in recursive functions
(* match-rec-functions.ml *)
let rec sum lst = match lst with
[]-> 0
|h::t -> h + sum t;;
let rec negate lst = match lst with
[]-> []
|h::t -> -h + negate t;;
let rec last lst = match lst with
[x]-> x
|h::t -> last t;;
let rec append l m = match l with
[]-> m
|h::t -> x :: (append t m)
let rec rev l = match l with
|[] -> []
| h::t -> append (rev t) (h::[])
(* rev is O(n^2) *)
(* can you do better? *)
Like Lists, but not really
(* tuples.ml *)
(1,2)
Tuples have a set Type
(* tuples-type.ml *)
(1,2) (* int * int *)
(1,"string",2.3) (* int * string * float *)
('a','b') (* char * char *)
['a';'b'] (* char list *)
[(1,2);(3,4)] (* (int * int) list *)
([1;2],[3;4]) (* int list * int list *)
Can Pattern Match
(* tuples-match.ml *)
let add t = match t with
(a,b) -> a + b
Remember Tuples have a type based on size
(* tuples-match-err.ml *)
let add t = match t with
(a,b) -> a + b
|(a,b,c) -> a + b + c
Like a weird hash
(* records.ml *)
type data = { month: string; dat: int; year: int };;
let today = { day=29; year=2020; month="feb"};;
O in OCaml stands for Object
(* record-access-1.ml *)
print_string today.month
Can also pattern match
(* record-access-2.ml *)
let { month=_; day = d} = today in
print_int d
We just saw this syntax
(* ud-types-alias.ml *)
type ilist = int list;;
let f x:ilist = [1;2;3;4];;
Ultimately not really useful in this form
Variant Types are more useful
(* ud-variants.ml *)
type parity = Even | Odd
Like an enum
(* pm-variants.ml *)
let swap x = match x with
Even -> Odd
|Odd -> Even
Can be Pattern Matched
Can Hold Data
(* ud-variants-1.ml *)
type parity = Even of int | Odd of int
Can still be Pattern Matched
(* pm-variants-1.ml *)
let add x = match x with
Even(x) -> Odd(x+1)
|Odd(x) -> Even(x+1)
Can Hold Data
Can be different
(* ud-variants-2.ml *)
type shape = Rect of int * int | Circle of float
Can still be Pattern Matched
(* pm-variants-2.ml *)
let area s = match s with
Rect (w,l) -> float_of_int (w*l)
|Circle r -> r *. r *. 3.14
Can be Recursive
(* llist.ml *)
type linked =
Item of string * linked
|Null;;
let head lst = match lst with
Item(x,_) -> x
|Null -> "";;
head (Item("Hello",Item("world", Null)));;
Can be generic
(* some_none.ml *)
type 'a option =
Some of 'a
|None
Built into OCaml