Standard ML
Functions
syntax: fun name (arg1: type1, .., argN: typeN) = body
type: name = type1 * ... * typeN -> body_type
lazy evaluation
Tuples
(* tuples *)
syntax: e = (e1, ..., en)
type: e1 * ... * en (can become fun's arguments list)
evaluation: #1 e, #2 e, ..., #n e
Lists
(* lists *)
syntax: l = [e1, ..., en]
type: [] = elem_type list; hd(head) l = elem_type, tl(tail) x = elem_type list
evaluation: cons = e :: l; null [] = false;
> 6 :: [1, 3, 5]
Let Expressions
syntax: let
b1 b2 ... bn
in
body
end
type: whole let type = body_type
evaluation: whole let result = body_result
Options
- NONE : type = 'a option
- SOME e: type =
e_typeoption - isSome: type = 'a option -> bool
- valOf : type = 'a option -> 'a
Boolean Operations
- e1 andalso e2: keyword
- e1 orelse e2 : keyword
- not e1 : bool -> bool
=(equal)<>(not equal)><>=<=: require two same type elem
Closure
Lexical Scope vs Dynamic Scope
- Lexical scope: function where defined.
- Dynamic scope: function where called.
Compose and Pipeline
fun sqrt_of_abs = Math.sqrt o Real.fromInt o abs
infix !>
fun x !> f = f x
fun sqrt_of_abs i = i !> abs !> Real.fromInt !> Math.sqrt
Curry and UnCurry
fun carry f x y = f (x, y)
fun unCarry f (x, y) = f x y
fun range (i, j) = if i > j then [] else i :: range(i+1, j)
fun countUp = curry range 1
val arr = countUp 7 (* maps to [1, 2, ..., 7] *)