Book Reading Report: Real World OCaml (2nd Edition) (Chapter 1-3)
Summary of Key Chapters
Chapter 1: A Guided Tour
REPL stands for Read, Evaluate, Print, and Loop,it is usually a environment where you can type in your code and get quick result
All the operation now are done in utop
(fancier REPL of ocaml) or the REPL of ocaml
This chapter covers the basics of OCaml, such as the most basic operator
1 | # 3 + 4;; |
Also introduces the most basic let-binding technique,which is essential for value-binding and function definition.
1 | # let x = 3 + 4;; (*Value Binding*) |
Also it introduces the if statement.
1 | # let sum_if_true test first second = |
Warning:
==
in ocaml means that two things are Physical equal,if you want to use structural equal or inequal please use=
for equal and<>
for inequal
Type inference and generic types are also important in Ocaml because this impoves the experience and overall type system.
1 | (*This is a function with full type notation*) |
Then it introduces some useful data structure that are essential in development such as
Tuples
Lists
Options
Record
Variants
Arrays
Mutable Record Fields
Refs
For basic loops conditioning ocaml supports for
and while
1 | (*While loop*) |
Chapter 2: Variables and Functions
Explains how to declare variables and functions in OCaml. Introduces the concept of immutability in OCaml variables.
Anonymous Functions is an important concept introduced in this chapter.it starts with The lambda calculus, developed in the 1930s by Alonzo Church,it is defined like this in ocaml
1 | # (fun x -> x + 1);; |
It can be used just as a normal function,you can apply it with value or pass it to other functions.
Also,the chapter introduces currying and uncurrying.
1 | let abs_diff x y = abs (x - y);; |
The key to interpreting the type signature of a curried function is the
observation that -> is right-associative
so
1 | int -> int -> int |
Also,ocaml introduces labeled arguments and optional arguments
label funtions can be passed with labels without caring of the order of the arguments,It does matter in a higher-order context,
e.g., when passing a function with labeled arguments to another function
optional arguments can be marked by using ?
in front of the name of the arguments,also you can provide a defualt value for optional arguments e.g ?(s="")
Chapter 3: Lists and Patterns
An OCaml list is an immutable, finite sequence of elements of the same type,and it can be expressed using a bracket-and-semicolon notation.
Also we can use ::
notation,which has the same meaning but more oftenly used in pattern matching.
1 | # [1;2;3];; |
In ocaml,the empty list []
is used to terminate a list,and []
can be a list of any type and can be combined with a list of any type.
we can extract data out of list using pattern matching in match guards in ocaml,such as
1 | let rec sum l = |
pattern matching is very efficent,but we need to consider the shaowding binding problem and exsaustive binding problem,we need to cover all the possible case in pattern matching.
There are some useful functions to play with lists in the standard library Base
1 | # List.reduce ~f:(+) [1;2;3;4;5];; |
This chapter also mentions tail recursion optmization,which is also an important technique in practice.
Considering this function
1 | # let rec length = function |
it’s great,but when the lists are too long (more than 100000 elements),it produces a stackoverflow exception,why?
To understand where the error in the above example comes from, you need to learn a
bit more about how function calls work. Typically, a function call needs some space to
keep track of information associated with the call, such as the arguments passed to the
function, or the location of the code that needs to start executing when the function call
is complete. To allow for nested function calls, this information is typically organized
in a stack, where a new
stack frame is allocated for each nested function call, and then
deallocated when the function call is complete.
So how can we solve this problem with only a few stack frame used?The answer is having a variable or a ref when doing recusion.
1 | # let rec length_plus_n l n = |
Also,there’s a common case for match xxx with … in ocaml,so there’s a sugar function
for it.
function
also defines a function but it only takes one param and it is nameless.
so we can write the original length
function like this
1 | # let rec length = function |
The optmization for recursive function and pattern matching are important,we should
Avoid using too much stack frame
Remove duplicate pattern which can cause reallocation
Make a good use of grammaratical sugar
Conclusion
The previous three chapters give us a brief overall introduction to the ocaml and functional programming.
Also it introduces the detail of the basic ocaml grammar and commonly used data structures.