Introduction to OCaml

advertisement
Introduction to OCaml
Slides prepared by Matt Gruskin
Some material borrowed from the
CIS 500 lecture notes
Functional Programming
• Persistent (immutable) data structures
– No assignments in pure functional programming!
• Recursion
– No loops in pure functional programming!
• Higher-order functions
– Functions that take other functions as arguments or
return functions as results
• OCaml is not a pure functional language
– OCaml does have for and while loops, but I won’t
show them here
Let statements
• Give a name to an expression or define a
function
# let pi = 3.1415;;
val pi : float = 3.1415
# pi;;
-: float = 3.1415
# let circle_area r = pi *. r *. r;;
val circle_area : float -> float = <fun>
# circle_area 4.0;;
- : float = 50.264
>>> pi = 3.1415;
>>> pi
3.1415000000000002
>>> def circle_area(r):
... return pi * r * r;
...
>>> circle_area(4);
50.264000000000003
Syntax differences from Python
• Method calls
– Parameters separated by spaces instead of
commas… and no parentheses around
parameter list
– Python: method(a,b,c)
– OCaml: method a b c
Type Inference
• Types are inferred (like Python)
– So you don’t have to give parameters types
• Unlike Python, types are inferred BEFORE
runtime
– When entering a function in the toplevel you’ll
see Param type -> param type -> … -> return type
– This is why different operators are needed for
different numeric types
# let circle_area r = pi *. r *. r;;
val circle_area : float -> float = <fun>
Lists
•
•
•
•
Similar to lists in Python
Unlike Python, implemented as linked lists
Cons – hd :: tl (hd is first element, tl is a list)
Unlike Python, lists are homogeneous
– You can do [5,’a’,True] in Python but you can’t do
[5;’a’;true] in OCaml
# let l = [1;3;5;7];;
val l : int list = [1; 3; 5; 7]
# l;;
- : int list = [1; 3; 5; 7]
>>> l = [1,3,5,7]
>>> l
[1, 3, 5, 7]
# [-1;0] @ l;;
- : int list = [-1; 0; 1; 3; 5; 7]
>>> [-1,0] + l
[-1, 0, 1, 3, 5, 7]
# List.hd l;;
- : int = 1
# List.tl l;;
-: int list = [3; 5; 7]
# List.nth l 2;;
- : int = 5
>>>
1
>>>
[3,
>>>
5
l[0]
l[1:]
5, 7]
l[2]
Recursive functions
let rec gcd a
if a=0 then
else if a>b
else gcd (b
b =
b
then gcd b a
mod a) a
def gcd(a,b):
if a == 0:
return b
if a > b:
return gcd(b,a)
return gcd(b % a, a)
let rec repeat k n =
if n=0 then []
else k :: repeat k (n-1)
def repeat(k,n):
if n == 0:
return []
else:
return [k] + repeat(k,n-1)
# repeat 1 4;;
- : int list = [1; 1; 1; 1]
>>> repeat(1,4)
[1, 1, 1, 1]
Pattern Matching
• Alternative to imperative statements like if,
switch
let rec gcd a
if a=0 then
else if a>b
else gcd (b
b =
b
then gcd b a
mod a) a
let rec gcd a b =
match a with
0 -> b
| x when x > b -> gcd b a
| _ -> gcd (b mod a) a
Tail Recursion
• Result of recursive call is also result of entire function
• In OCaml, tail recursion uses constant stack space
let rec rev l =
match l with
[] -> []
| hd :: tl ->
(rev tl) @ [hd]
def rev(l):
if l == []:
return []
else:
return rev(l[1:]) + [l[0]]
let rec tailrev l r =
match l with
[] -> r
| hd :: tl ->
tailrev tl (hd :: r)
def tailrev(l,r=[]):
if l == []:
return r
else:
return tailrev(l[1:],[l[0]]+r)
let rec tailrev ?(r=[]) l =
match l with
[] -> r
| hd :: tl ->
tailrev ~r:(hd :: r) tl
Functions as parameters
# let l = [3;5;7];;
val l : int list = [3; 5; 7]
>>> l = [3,5,7]
# List.map (fun x -> x*2) l;;
-: int list = [6; 10; 14]
>>>
[6,
>>>
[6,
# List.fold_left (fun x y -> x + y) 0 l;;
-: int = 15
>>> reduce(lambda x,y:x+y,l,0)
15
# List.filter (fun x -> x > 4) l;;
- : int list = [5; 7]
>>> filter(lambda x: x>4,l)
[5, 7]
# List.iter (Printf.printf "%i\n") l;;
3
5
7
: unit = ()
>>> for x in l:
...
print x
...
3
5
7
map(lambda x: x*2,l)
10, 14]
[x*2 for x in l]
10, 14]
Quicksort
PYTHON
def sort(a):
if a == []:
return []
else:
pivot = a[0]
left = [x for x in a if x < pivot]
right = [x for x in a[1:] if x >= pivot]
return sort(left) + [pivot] + sort(right)
OCaml
let rec quicksort l =
match l with
[] -> []
| pivot :: t ->
let left = List.filter (fun x -> x < pivot) t in
let right = List.filter (fun x -> x >= pivot) t in
(quicksort left) @ [pivot] @ (quicksort right)
Palindrome
PYTHON
def palindrome(s):
if len(s) <= 1:
return True
return s[0] == s[-1] and palindrome(s[1:-1])
OCaml
let rec palindrome s =
s = (tailrev s)
Download