Basic types Numbers int (various precisions) real (64 bit floats) Usual arithmetic operators Surpises: ~3 -- notation for negative numbers ~(1+2) -- unary negation 4 div 2 instead of 4/2 but 4.0/2.0 -- / is for real division Unsigned ints are called words: 0w32: word +, -, * are overloaded on int, real, word types 1+2 1.0+2.0 0w1+0w2 but with default resolution: fn x => x + x : int -> int (not real -> real) Only a subset of arithmetic operators are "pervasive" (globally defined) quot(4,2) -- need to say Int.quot(4,2) -------------------------- Strings and chars "abc" "a\tb\nc" : string "\065" == "A" -- decimal numeric escape codes "ab" ^ "cd" -- concatenation #"a" : char explode "abc" ==> [#"a", #"b", #"c"] Relational operators: < > <= >= These are overloaded for int, real, string Converting numbers to/from strings: Int.toString 342; Real.toString 3.14; ------------------------- Booleans true: bool false : bool not : bool -> bool andalso, orelse -- short-circuit boolean connectives Conditional expression if _ then _ else _ (always two branches) ------------------------- Compound data Tuples (Cartesian products) (3, true) : int * bool -- heterogeous element types, fixed length ("abc", 1.0, 3) : string * real * int #2 ("abc", 1.0, 3) ==> 1.0 -- selection Lists nil, [] -- the empty list 1 :: 2 :: 3 :: nil -- cons operation, right associative [1,2,3] ( = 1 :: 2 :: 3 :: nil ) -- shorthand literal list notation operations: null, hd, tl, @ (append), concat, rev ------------------------ Functions (anonymous) fn x => x + 1 : int -> int -- \x.x+1 in lambda calculus fn x => x : 'a -> 'a ------------------------- Declarations: Values val x = 3 -- simple value declaration (x is a name for 3) val (x,y) = (3,4) -- pattern binding (x == 3, y == 4) val x::xs = [1,2,3] -- x == 1, y == [2,3] val increment = fn x => x + 1 val fact = fn n => if n = 0 then 1 else n * fact(n-1) -- doesn't work! val rec fact = fn n => if n = 0 then 1 else n * fact(n-1) -- recursive, ok - alternatively, for (recursive or nonrecursive) functions: fun fact n = if n = 0 then 1 else n * fact(n-1) -- equivalent to val rec - sequential val declarations val a = 3 val b = a + 2 -- (b = 5) - simultaneous val declarations val a = 1 val a = 3 and b = a + 2 -- (b = 3) Types type sterling = int * int * int datatype tree = Leaf | Node of int * tree * tree type 'a pair = 'a * 'a type 'a alist = (string * 'a) list -- association list Exceptions (later) ------------------------ Static Scoping and function closures val a = 3 fun f y = y + a (* a closure, a is frozen *) val a = 1 f 5 ==> 8 -------------- val a = ref 3 fun f y = y + !a (* a closure, a is frozen, but mutable *) a := 1 f 5 ==> 6 ------------------------ Let expressions let in is the scope of the declarations val a = 3 val f = let val a = 1 in fn y => y + a end a ==> 3 f 5 ==> 6 Local declarations local val a = 3 in fun f y = y + a end f 5 ==> 8