1. BASIC DATA TYPES: int, bool
Rich type system and polymorphism in ocaml. Types are infered not declared.
Basic types: int, bool, float, string, char, ...
int
value: \(-2^{62}\) ~ \(2^{62}-1\) on 64-bit machines.
ops: +, -, *, /, mod
(reminder: /
is integer division)
# 3+2*4-1;;
- : int = 10
# 5/2;;
- : int = 2
# -5 mod 3;;
- : int = -2
bool
values: true, false
ops: &&,||, not
comparison ops: <, >, =, <=, =>, <>
note 1: comparisons must have the same type of operands)
note 2: equal test is =
, =
is NOT assigment. ==
exists but is for something else...
# true && (1<7);;
- : bool = true
# 1.0 < 7;;
Error: This expression has type int but an expression was expected of type
float
# 5 > "hello";;
Error: This expression has type string but an expression was expected of type
int
# 3=3;;
- : bool = true
# 3==3;;
- : bool = true
# 3<3.0;;
Error: This expression has type float but an expression was expected of type
int
# 3.0 < 3.0;;
- : bool = false
2. MORE DATA TYPES: float, char, string
float
value: must written with a dot (5.0
, 5.
), or exponential (5e3
, 6e-9
)
ops: also have a dot in the end +.
, -.
, *.
, /.
functions: sqrt, sin, cos, ceil, floor, ...
# 3.0 +. 1e10;;
- : float = 10000000003.
# 2 + 3.0;;
Error: This expression has type float but an expression was expected of type
int
# 3. +. 2.0;;
- : float = 5.
All basic types are disjoint: no value belongs to 2 different basic types, no implicit conversion.
conversion functions in both directions:
float_of_int
: int -> floatint_of_float
: float -> int
# float_of_int(2);;
- : float = 2.
# int_of_float(2.4);;
- : int = 2
# float_of_int 2;;
- : float = 2.
# int_of_float 2.8;;
- : int = 2
Parentheses only necessary to indicate structure.
char
values: 256 chars (0~255), can be written as 'a
' or '\087
'
conversion functions (char ↔ int):
Char.chr
: int ->charChar.code
: char -> int
# Char.code 'A';;
- : int = 65
# Char.code '\122';;
- : int = 122
# Char.chr 233;;
- : char = '\233'
# Char.chr 65;;
- : char = 'A'
# Char.chr (Char.code 'B');;
- : char = 'B'
string
values: written between ""
ops: ^
for string concatenation
functions: String.length, int_of_string, float_of_string, String.get(s,i) ...
# "abc" ^ "def";;
- : string = "abcdef"
# String.length "1234";;
- : int = 4
# int_of_string "123";;
- : int = 123
# int_of_string "123a";;
Exception: Failure "int_of_string".
# string_of_int 123;;
- : string = "123"
# String.get "abc" 1;;
- : char = 'b'
3. EXPRESSIONS: if-then-else, func-applications and operators
expressions are used to compute values.
conditional expr
if... then... else...
⇒ this gives an expression, not an instruction.
An expression always have a type, type of the if-then-else expression is the type of the expressions in then and else, which must be the same.
If the else
is missing → there is a default value, to be discussed later
# if 1<2 then 8 else 9;;
- : int = 8
# if 6=8 then 1 else 8;;
- : int = 8
# if 6=8 then 1 else 8.;;
Error: This expression has type float but an expression was expected of type
int
# if(if 1=1 then 2=2 else 3>2) then 2<3 else 3<2;;
- : bool = true
function application
again, ()
are not needed unless indicate structure, and parentheses are NOT function applications...
# String.get;;
- : string -> int -> char = <fun>
# String.get "abcde" 2;;
- : char = 'c'
# String.get ("Hello"^"world") (3+2);;
- : char = 'w'
# String.get (string_of_int 65) (int_of_string "0");;
- : char = '6'
# String.get("hello", 2);;
Error: This expression has type 'a * 'b
but an expression was expected of type string
Polymorphic operators
Some ops have polymorphic(generic) types, like >
: 'a → 'a → bool
Here the 'a
is a type variable, can be instantiated by any type.
# 12 > 23.0;;
Error: This expression has type float but an expression was expected of type
int
# 'a' > 'b';;
- : bool = false
# "hello" > "world";;
- : bool = false
4. DEFINITIONS
definitions are used to give names to values, in ocaml there are global defs and local defs.
global definition
effective for rest of session
syntax: let name = expr
once set, the value of the identifier never changes.
# let x = 2+3;;
val x : int = 5
# let y = 2*x;;
val y : int = 10
# let x = 3;; # **the old definition of x will be shadowed**
val x : int = 3
# x = x+1;;
- : bool = false
local definition
naming within a delimited scope
syntax: let name = expr1 in expr2
the scope of the identifier is expr2
, the result's value is also expr2's value. So the identifier should appear in expr2.
# let x = 9 in 2*x;;
- : int = 18
# x;; # x is not in global scope
Error: Unbound value x
# let y = x+1 in y/3;;
Error: Unbound value x
# let x = 17;; # now x is global
val x : int = 17
# let y = x+1 in y/3;;
- : int = 6
local defs can be nested:
# let x = 4 in
let y = x+1 in
let x = 2*y in x;;
Error: Syntax error
# let x = 4 in
let y = x+1 in
let x=2*y in x;;
- : int = 10
# let x = 4 in
(let x=17 in x+1) + x;;
- : int = 22
Simultaneous Definitions
can assign 2 identifiers in the same line:
# let x1=2 and x2=3-3;;
val x1 : int = 2
val x2 : int = 0
Note: expr
is evaluated w.r.t. the value bindings before the let
.
# let x=2 in
let y=x+1 in (*y=2+1*)
x*y;;
- : int = 6
# let x=1;;
val x : int = 1
# let x=2 and y=x+1 in (*y=1+1 because the binding for x before the let is 1!*)
x*y;;
- : int = 4
5. FUNCTIONS
func definition
global function (with 1 argument) def : let f x = expr
local def: let f x = expr1 in expr2
# let f x = x+1;;
val f : int -> int = <fun>
# f 17;;
- : int = 18
# let g y = 2*y
in g 42;;
- : int = 84
# f f 1;; (* interpreted as apply 2 argments to f, need parentheses here*)
Error: This function has type int -> int
It is applied to too many arguments; maybe you forgot a `;'.
# f (f 1);;
- : int = 3
lexical scoping
def. lexical scoping identifiers(names) used in function body refers to the names that are visible at the moment of function definition.
def. dynamic scoping names refer to names that are visible at the moment of function invocation.
# let f x = x+1 in
let g y = f (f y) in (*here f is the f defined above, which is visible at the moment of g's declaration*)
let f x = 2*2 in (*this f is visible after g's declaration, it is visible when g is invocated*)
g 5;; (*g uses the first f*)
Warning 26: unused variable f.
- : int = 7
(*the same is true for global scoping*)
# let f x = x+1;;
val f : int -> int = <fun>
# let g y = f (f y);;
val g : int -> int = <fun>
# let f x = 2*x;;
val f : int -> int = <fun>
# g 5;;
- : int = 7
identifiers are NOT variables
A name(identifier) can be hidden (the value is NOT changed) by a new definition of the same name.
The hidden identifier can be accessed with static(lexical) binding:
# let a = 1;;
val a : int = 1
# let f x = x+a;;
val f : int -> int = <fun>
# f 2 ;;
- : int = 3
# let a = 73;;
val a : int = 73
# f 2;; (*f still uses a's value as 2, the old value of a is NOT changed, it's hidden --closure? *)
- : int = 3
6. RECURSION
rec functions are natural on recursively defined data structures.
example: fact(n)
recursive definition
using the f
in let's expr
will cause pb as f
refers to the previous value of f
. ⇒ use key word rec
.
# let fact n = if n<=1 then 1 else n*fact(n-1);;
Error: Unbound value fact
# let rec fact n = if n<=1 then 1 else n*fact(n-1);;
val fact : int -> int = <fun>
# fact 10;;
- : int = 3628800
mutually recursive function
ex. 2 funcs calling each other recursively
⇒ use simultaneous defs (let...and...
):
# let rec even x = if x=0 then true else odd(x-1)
and odd x = if x=0 then false else even(x-1);;
val even : int -> bool = <fun>
val odd : int -> bool = <fun>
# even 17;;
- : bool = false
# odd 10;;
- : bool = false
exercices
let multiple_of n d =
(n mod d) == 0;;
let integer_square_root n =
let sqr = sqrt (float_of_int n) in
int_of_float sqr;
let rec gcd n m =
let big = max n m and small = min n m in
let r = big mod small in
if r=0 then small
else gcd r small;;
let rec multiple_upto n r =
if r<2 then false
else if multiple_of n r then true
else multiple_upto n (r-1);;
let is_prime n =
if n<=1 then false
else not (multiple_upto n (n-1));;
Part 2 of series «Introduction to Functional Programming in OCaml»:
- [OCaml MOOC] week0: intro and overview
- [OCaml MOOC] week1: BASIC TYPES, DEFINITIONS AND FUNCTIONS
- [OCaml MOOC] week2: BASIC DATA STRUCTURES
- [OCaml MOOC] week3: MORE ADVANCED DATA STRUCTURES
- [OCaml MOOC] week4: HIGHER ORDER FUNCTIONS
- [OCaml MOOC] week5: EXCEPTIONS, INPUT OUTPUT AND IMPERATIVE CONSTRUCTS
- [OCaml MOOC] week6: MODULES AND DATA ABSTRACTION
Disqus 留言