OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml Classics
EPITA - Practical Programming02 - Return of the Objective Caml
Marwan Burelle
[email protected]://wiki-prog.infoprepa.epita.fr
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml Classics
Outline
1 OCaml BasicsFuntionsPrograms StructureCompiling !
2 OCaml And Imperative ProgrammingCan I Haz Loop ?Mutable Data
3 Exceptions
4 OCaml ClassicsPlay With IntListsBinary Tree
OCaml Returns
Marwan Burelle
BasicsFuntions
Programs Structure
Compiling !
Mutable
Exceptions
OCaml Classics
OCaml Basics
OCaml Basics
OCaml Returns
Marwan Burelle
BasicsFuntions
Programs Structure
Compiling !
Mutable
Exceptions
OCaml Classics
OCaml Quick Overview
• OCaml is functional and strongly typed language• It’s a variant of ML and thus provides type inference• It has a well founded semantics• It provides higher-order: function are first-class entity• It provide safe mutability (and thus imperative
features)• It provides an object model• It provides a powerful module sub-language• It can be interpreted (interactively or not), compiled
into bytecode or native code.
OCaml Returns
Marwan Burelle
BasicsFuntions
Programs Structure
Compiling !
Mutable
Exceptions
OCaml Classics
Overview
1 OCaml BasicsFuntionsPrograms StructureCompiling !
OCaml Returns
Marwan Burelle
BasicsFuntions
Programs Structure
Compiling !
Mutable
Exceptions
OCaml Classics
In The Beginning Was Functions
The most basic expression is functional value
functional value(function x -> x + 1)
OCaml Returns
Marwan Burelle
BasicsFuntions
Programs Structure
Compiling !
Mutable
Exceptions
OCaml Classics
Functions Can Be Applied
Applications(function x -> x + 1) 41
Applications can be reduced to closed value (here 42)
OCaml Returns
Marwan Burelle
BasicsFuntions
Programs Structure
Compiling !
Mutable
Exceptions
OCaml Classics
Naming
Functional and closed values can be named for latter use
Naming valuelet f = function x -> x + 1 inlet res = f 20 in 2 * res
Naming can be local (as in previous example) or global
Global naminglet f = function x -> x + 1
OCaml Returns
Marwan Burelle
BasicsFuntions
Programs Structure
Compiling !
Mutable
Exceptions
OCaml Classics
Function Definitions
Syntax: Function Definitionlet f = function x -> e(* e is an expression where x is free *)
Syntax: Sugarlet f = fun x -> elet f x = e
Syntax: Multiple Parameterslet f = function x -> function y -> x + ylet f = fun x -> fun y -> x + ylet f = fun x y -> x + ylet f x = function y -> x + ylet f x = fun y -> x + ylet f x y = x + y
OCaml Returns
Marwan Burelle
BasicsFuntions
Programs Structure
Compiling !
Mutable
Exceptions
OCaml Classics
Curryfied Form
• In OCaml, like in λ−calculus, function always onlyone parameter
• Multiple parameters is obtain by returning a function
Application and Multiple Argumentslet r = (((fun x -> fun y -> x + y) 2) 40)let r’ = (fun x -> fun y -> x + y) 2 40
OCaml Returns
Marwan Burelle
BasicsFuntions
Programs Structure
Compiling !
Mutable
Exceptions
OCaml Classics
Examples
Fact !let rec fact n =if n < 2 then 1else n * fact (n-1)
Fact with pattern matchinglet rec fact = function| 0 | 1 -> 1| n -> n * fact (n-1)
Fast Powerlet rec power x = function| 0 -> 1| p ->
(power (x*x) (p/2))* (if p mod 2 = 0 then 1 else x)
OCaml Returns
Marwan Burelle
BasicsFuntions
Programs Structure
Compiling !
Mutable
Exceptions
OCaml Classics
Overview
1 OCaml BasicsFuntionsPrograms StructureCompiling !
OCaml Returns
Marwan Burelle
BasicsFuntions
Programs Structure
Compiling !
Mutable
Exceptions
OCaml Classics
Where Are Double Semi-Colons ?
• Double semi-colons (;;) are useless• Unless: you’re using interactive mode or you’re using
toplevel expressions.• Don’t use double semi-colons !
Double semi-colons are uselesslet f a b = a + blet ref fibo = function| (0 | 1) as n -> n| n -> fibo (n-1) + fibo (n-2)
OCaml Returns
Marwan Burelle
BasicsFuntions
Programs Structure
Compiling !
Mutable
Exceptions
OCaml Classics
OCaml Code
• Toplevel (outside of any context) phrase must bedefinitions (names, types, modules . . . )
• Avoid toplevel expressions: they are meaningless anderror prone
• It is a good idea to build a main function to clarify theentry-point
A Simple Program(* The main function *)let main () =beginPrintf.printf "Hello World !\n";exit 0
end(* Starting Point *)let _ = main ()
OCaml Returns
Marwan Burelle
BasicsFuntions
Programs Structure
Compiling !
Mutable
Exceptions
OCaml Classics
What’s Wrong With Toplevel Expressions
Interactive Session# 1 + 1;;- : int = 2
But what happen if I do that in a program ?Example:
> cat foo.ml1 + 1;;> ocamlopt -o foo foo.ml> ./foo>
We got a program that seems to do nothing (but it may consumesome cycles for that . . . )
OCaml Returns
Marwan Burelle
BasicsFuntions
Programs Structure
Compiling !
Mutable
Exceptions
OCaml Classics
Typical Structures of an OCaml Program
Program Structure(* definitions *)type t = BAD | GOODlet x = 42let f x = x + 1let to_bool = function| BAD -> false| GOOD -> true
(* Entry Point *)let main () =beginPrintf.printf "Hello World !\n";exit 0;
endlet _ = main ()
OCaml Returns
Marwan Burelle
BasicsFuntions
Programs Structure
Compiling !
Mutable
Exceptions
OCaml Classics
Overview
1 OCaml BasicsFuntionsPrograms StructureCompiling !
OCaml Returns
Marwan Burelle
BasicsFuntions
Programs Structure
Compiling !
Mutable
Exceptions
OCaml Classics
Choose Your Kind
• ocamlc: the bytecode compiler:• Bytecode is almost portable• Available on all POSIX system supported by gcc• Offer interesting debugging facilities• Produced code is (very) slow
• ocamlopt: the native compiler:• Produce fast code (from 5 to 15 time faster than
bytecode)• Easier interface with other language• Available only a limited set of architecture (x86, ARM,
Power, SPARC . . . )• Compilation is sometime slower
• ocamlc -cutom: produce a standalone bytecodebased program by combining the VM and thebytecode, you don’t want it.
OCaml Returns
Marwan Burelle
BasicsFuntions
Programs Structure
Compiling !
Mutable
Exceptions
OCaml Classics
Basic Compilation
foo.mllet main () =beginPrintf.printf "Hello World !\n";exit 0;
endlet _ = main ()
Example:> lsfoo.ml> ocamlopt -o foo foo.ml> lsfoo foo.cmi foo.cmx foo.ml foo.o> ./fooHello World !>
OCaml Returns
Marwan Burelle
BasicsFuntions
Programs Structure
Compiling !
Mutable
Exceptions
OCaml Classics
The Command Line
cmd.mllet main () =beginArray.iter (Printf.printf "| %S ") Sys.argv;Printf.printf "|\n";exit 0;
endlet _ = main ()
Example:> ocamlopt -o cmd cmd.ml> ./cmd a aa bb "a b c"| "./cmd" | "a" | "aa" | "bb" | "a b c" |>
OCaml Returns
Marwan Burelle
BasicsFuntions
Programs Structure
Compiling !
Mutable
Exceptions
OCaml Classics
ocamlbuild
• ocamlbuild is an automatic build system for OCaml• It’s more effective for multiple files project• For most basic example it can be used without any
configuration
Example:> lsfoo.ml> ocamlbuild foo.nativeFinished, 4 targets (0 cached) in 00:00:00.> ls_build foo.ml foo.native> ./foo.nativeHello World !> ocamlbuild -cleanFinished, 0 targets (0 cached) in 00:00:00.00:00:00 0 (0 ) STARTING> lsfoo.ml
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
OCaml And Imperative Programming
OCaml And ImperativeProgramming
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
Pure Or Not. Pure, That’s The Question !
• Pure Functions are deterministic applications thatmap values (its argument) to a unique result.
• The behavior of a pure function is not affected byelements of the program state outside of its arguments,nor does it affect elements outside of its result.
• Theoretically, any possible behavior can be obtainedwith pure functions, mostly by passing and returningmemory states.
• OCaml choose the pragmatic approach: they breakpurity.
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
Overview
2 OCaml And Imperative ProgrammingCan I Haz Loop ?Mutable Data
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
Why Loop Are Not Functional
Example:x = 0;while x < 10 doprint(x);x = x + 1;
done
Can I do that as is in OCaml ?Fail Loop
let x = 0 inwhile x < 10 doPrintf.printf "%d\n" x;(* Now increase x ? *)let x = x + 1 (* OK *)in (* Now what ? *) ()
done
Fail !
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
Basic For Loop
For the basic cases (bounded iteration) OCaml providessimple for loops without the need of any variables orside-effect operators:
For Loopfor i = 0 to 10 doPrintf.printf "%d\n" i
done
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
A Simple Example
Command Line With Looplet main () =beginfor i = 0 to (Array.length Sys.argv) - 1 doPrintf.printf "| %S " Sys.argv.(i)
done;Printf.printf "|\n";exit 0;
endlet _ = main ()
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
Overview
2 OCaml And Imperative ProgrammingCan I Haz Loop ?Mutable Data
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
Mutable ?
• Bounded iterations (for loops) aren’t sufficient toexpress all possible all algorithms (but, anyway,recursion is enough.)
• Sometimes we may also want to change the state ofmemory elements.
• But, since we’re using OCaml, we want to keep mostsafety properties of the language.
• Mutable entities should verify the followingproperties to be safe:• Existence: if a symbol exists, it references a valid
memory cell• Initialization: a memory cell always have a defined
value• Stability: the kind of the content of a memory cell
should not change
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
References
References are simplest mutable data in OCaml, it’s a kind ofsafe pointer.
references.mllet main () =beginlet r = ref 0 inPrintf.printf "r = ref %d\n" !r;r := 41;Printf.printf "r = ref %d\n" !r;r := !r + 1;Printf.printf "r = ref %d\n" !r;exit 0;
endlet _ = main ()
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
Some Examples
Basic While Looplet r = ref 0 inwhile !r < 10 doPrintf.printf "%d\n" !r;r := !r + 1;
done
incr and decr(* Already available in Pervasive module *)let incr r = r := !r + 1let decr r = r := !r - 1
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
Some Examples
Fact !let fact n =if n < 2 then 1elsebeginlet r = ref 1 infor i = n downto 1 dor := !r * i;
done;!r
end
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
Closures
closures.mllet f1 = Printf.printf "f1\n"let f2 () = Printf.printf "f2\n"let f3 = fun _ -> Printf.printf "f3\n"let f4 = Printf.printf "f4 (1)\n";fun _ -> Printf.printf "f4 (2)\n"
let main () =Printf.printf "\nMain\n";f1; f2 (); f3 (); f4 (); exit 0
let _ = main ()
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
Closures
closures.ml> ./closures.nativef1f4 (1)
Mainf2f3f4 (2)
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
Closures And References
next.mllet next =let r = ref 0 infun () ->r := !r + 1;!r
let main () =beginfor i = 1 to 10 doPrintf.printf "%d " (next ())
done;Printf.printf "\n";exit 0;
endlet _ = main ()
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
Closures And References
Example:
> ocamlbuild next.nativeFinished, 4 targets (0 cached) in 00:00:00.> ./next.native1 2 3 4 5 6 7 8 9 10>
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
Arrays And Strings
Arrays and strings are mutable !mutable_array.ml
let main () =let t = Array.make 3 0 inArray.iteri (Printf.printf "t.(%d) = %d ") t;Printf.printf "\n";t.(1) <- 42;Array.iteri (Printf.printf "t.(%d) = %d ") t;Printf.printf "\n";exit 0
let _ = main ()
Example:
> ./mutable_array.nativet.(0) = 0 t.(1) = 0 t.(2) = 0
t.(0) = 0 t.(1) = 42 t.(2) = 0
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
Arrays And Strings (2)
mutable_strings.mllet main () =beginlet s = "abcd" inPrintf.printf "%S\n" s;s.[3] <- ’e’;Printf.printf "%S\n" s;exit 0;
endlet _ = main ()
Example:
> ocamlbuild mutable_strings.nativeFinished, 4 targets (0 cached) in 00:00:00.> ./mutable_strings.native"abcd""abce"
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
Records
OCaml provides traditional records. Record’s field can bemarked as mutable.
Example of Recordslet next = let c = ref 0 in fun _ -> incr c;!c
type person = {name : string;uniq_id : int;mutable visit_count : int;
}
let new_person n ={ name=n; uniq_id= next (); visit_count=0 }
let visiting p =p.visit_count <- p.visit_count + 1
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
More On Records
Fun With Recordstype state = NIL | MODIFIED | EXCLUSIVE | SHARED | INVALIDtype cache_line = {addr : nativeint;content : nativeint array;mutable cache_state : state;
}
let new_line addr = {addr = addr; cache_state = NIL;content = Array.make 16 (0n);
}
let invalidate addr lines = Array.iter(function| { cache_state = SHARED } as l
when l.addr = addr -> l.cache_state <- INVALID| _ -> ()
) lines
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
Smart Copy
Smart Record Copytype entity = {id : int;mutable x: float; mutable y: float; mutable z: float;mutable dx: float; mutable dy: float; mutable dz: float;
}
let base_entity = {id = -1;x = 0.; y = 0.; z = 0.;dx = 0.; dy = 0.; dz = 0.;
}
let new_entity ={ base_entity with id = next (); }
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
Beware When Copying
records.mltype t = {a : int ref;mutable b : int;
}let r = { a = ref 0; b = 0 }let r’ = { r with b = 1; }let main () =beginr.a := 42; r.b <- 42;Printf.printf "r’.a = ref %d\nr’.b = %d\n"!(r’.a) r’.b;
endlet _ = main ()
Example:
> ./records.nativer’.a = ref 42r’.b = 1
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
Beware When Copying
records.mltype t = {a : int ref;mutable b : int;
}let r = { a = ref 0; b = 0 }let r’ = { r with b = 1; }let main () =beginr.a := 42; r.b <- 42;Printf.printf "r’.a = ref %d\nr’.b = %d\n"!(r’.a) r’.b;
endlet _ = main ()
Example:
> ./records.nativer’.a = ref 42r’.b = 1
OCaml Returns
Marwan Burelle
Basics
MutableCan I Haz Loop ?
Mutable Data
Exceptions
OCaml Classics
Records And References
Interactive Session# ref 0;;- : int ref = {contents = 0}
References are, in fact, syntactic sugar on records.
Theoretical Definitions of type reftype ’a ref = { mutable contents : ’a }
Some consequences
Alternative syntaxlet x = ref 0 inx.contents <- 1; (* same as x := 1 *)(x.contents = !x) (* always true *)
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml Classics
Exceptions ?
• Exceptions mechanism allows programmer to triggerspecific behavior in some particular cases.
• Exceptions are used to get out of the normal flow ofexecutions: when an exception is raised, the programescapes the current call-stack until the exception iscatched or the program dies.
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml Classics
Declaring Exceptions
• You can define your own exceptions• An exception as the same syntax as data-type tag and
can have parameters• All the exceptions have the exn and can be used as
value.Declaring exception
(* A Simple exception without parameter *)exception MyFstException
(* With two parameters: an int and a string *)exception WrongParameters of int * string
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml Classics
Exception: Without Catching
Entry Point
1st Function
2nd Function
3rd Function
exception
Program Boundary
call
call
call
Error: uncaught exception
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml Classics
Raising Exceptions
fail.mlexception MyFailure of int * int
let thrd_fun i j =beginPrintf.printf "3rd function\n%!";ignore (raise (MyFailure(i,j)));Printf.printf "After raise\n%!";
endlet snd_fun i j =Printf.printf "2nd function\n%!";thrd_fun i j
let fst_fun i j =Printf.printf "1st function\n%!";snd_fun i j
let main () =fst_fun 42 666
let _ = main ()
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml Classics
Raising Exceptions
fail.ml> ./fail.native1st function2nd function3rd functionFatal error: exception Fail.MyFailure(42, 666)
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml Classics
Using Predefined Exception
List.assoclet rec assoc x = function| [] -> raise Not_found| (k,v)::_ when x=k -> v| _::t -> assoc x t
failwith and invalid_arglet failwith s = raise (Failure s)let invalid_arg s = raise (Invalid_argument s)
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml Classics
Catching Exceptions
Entry Point
1st Function
2nd Function
3rd Function
exception
Program Boundary
call
call
call
try … with
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml Classics
Catching Exceptions
fail2.mlexception MyFailure of int * int
let thrd_fun i j =beginPrintf.printf "3rd function\n%!";ignore (raise (MyFailure(i,j)));Printf.printf "After raise\n%!";
endlet snd_fun i j =Printf.printf "2nd function\n%!";thrd_fun i j
let fst_fun i j =Printf.printf "1st function\n%!";try snd_fun i j with| MyFailure (x,y) ->Printf.eprintf "catched MyFailure (%d,%d)\n%!" x y
let main () =fst_fun 42 666
let _ = main ()
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml Classics
Catching Exceptions
fail.ml> ./fail2.native1st function2nd function3rd functionFatal error: exception Fail.MyFailure(42, 666)
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml ClassicsPlay With Int
Lists
Binary Tree
OCaml Classics
OCaml Classics
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml ClassicsPlay With Int
Lists
Binary Tree
Overview
4 OCaml ClassicsPlay With IntListsBinary Tree
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml ClassicsPlay With Int
Lists
Binary Tree
Example
fact and fibo(* Factorial (tail recursive) *)let fact n =let rec aux a = function| 0 | 1 -> a| n -> aux (n*a) (n-1)
in aux 1 n
(* Fibonacci (naive version) *)let rec fibo = function| (0|1) as x -> x| n -> fibo (n-1) + fibo (n-2)
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml ClassicsPlay With Int
Lists
Binary Tree
Example
Smarter fibo(* Fibonacci (linear-tail recursive version) *)let linear_fibo n =let rec aux f1 f2 x =if x = n then f1else aux (f1 + f2) f1 (x + 1)
inmatch n with| 0 | 1 -> n| _ when n < 0 -> -1| _ -> aux 1 0 1
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml ClassicsPlay With Int
Lists
Binary Tree
Example
Power And Square Rootlet rec power x = function| 0 -> 1 | 1 -> x| p -> (power (x*x) (p/2))
* (if p mod 2 = 0 then 1 else x)
let rec numbits a = function| 0 -> a| n -> numbits (a+1) (n lsr 1)
let int_sqrt n =let init = (1 lsl (1+((numbits 0 n)-1)/2)) inlet rec aux x =let y = (x + n/x)/2 inif y >= x then xelse aux y
in aux init
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml ClassicsPlay With Int
Lists
Binary Tree
Overview
4 OCaml ClassicsPlay With IntListsBinary Tree
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml ClassicsPlay With Int
Lists
Binary Tree
Example
Length And nth(* List.length *)let length l =let rec aux len = function| [] -> len| a::l -> aux (len + 1) l
in aux 0 l
(* List.nth *)let nth l n =(* Avoid stupid calls *)if n < 0 then invalid_arg "List.nth" elselet rec nth_aux n = function| [] -> failwith "nth"| a::l ->if n = 0 then a else nth_aux (n-1) l
in nth_aux n l
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml ClassicsPlay With Int
Lists
Binary Tree
Example
Rev And Append(* List.rev_append *)let rec rev_append l1 l2 =match l1 with| [] -> l2| a :: l -> rev_append l (a :: l2)
(* List.rev *)let rev l = rev_append l [](* List.append or @ *)let append l1 l2 =rev_append (rev l1) l2
(* List.flatten *)let rec flatten = function
[] -> []| l::r -> l @ flatten r
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml ClassicsPlay With Int
Lists
Binary Tree
Example
Lists iterators(* List.map *)let rec map f = function| [] -> []| a::l -> let r = f a in r :: map f l
(* List.iter *)let rec iter f = function| [] -> ()| a::l -> f a; iter f l
(* List.rev_map *)let rev_map f l =let rec rmap_f accu = function| [] -> accu| a::l -> rmap_f (f a :: accu) l
inrmap_f [] l
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml ClassicsPlay With Int
Lists
Binary Tree
Example
Folds(* List.fold_left *)let rec fold_left f accu l =match l with| [] -> accu| a::l -> fold_left f (f accu a) l
(* List.fold_right *)let rec fold_right f l accu =match l with| [] -> accu| a::l -> f a (fold_right f l accu)
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml ClassicsPlay With Int
Lists
Binary Tree
Overview
4 OCaml ClassicsPlay With IntListsBinary Tree
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml ClassicsPlay With Int
Lists
Binary Tree
Example
Binary Treetype ’a tree =| Empty| Node of ’a tree * ’a * ’a tree
(* A size function with all special cases *)let rec size = function| Empty -> 0| Node (Empty, _, Empty) -> 1| Node (child, _, Empty)| Node (Empty, _, child)-> 1 + size child
| Node (left, _, right)-> 1 + size left + size right
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml ClassicsPlay With Int
Lists
Binary Tree
Example
Depth First Traversallet rec height = function| Empty -> -1| Node (left, _, right)-> 1 + max (height left) (height right)
let rec prefix accu = function| Empty -> accu| Node (left, k, right)-> k :: prefix (prefix accu right) left
let rec prefix_print print = function| Empty -> ()| Node (left, k, right) ->print k;prefix_print print left;prefix_print print right
OCaml Returns
Marwan Burelle
Basics
Mutable
Exceptions
OCaml ClassicsPlay With Int
Lists
Binary Tree
Example
Breadth First Traversallet breadth_first print t =let q = Queue.create () inbeginif t <> Empty then Queue.push t q;Queue.push Empty q;while not (Queue.is_empty q) domatch Queue.take q with| Empty ->Printf.printf "\n";if not (Queue.is_empty q) thenQueue.push Empty q;
| Node (left,k,right) ->print k;if t <> Empty then Queue.push left q;if t <> Empty then Queue.push right q;
done;end