Let`s talk about SML, functional programming
Table of Contents
variable binding
Define new variable; this means that the values are bound
val x = e;
syntax:
- Keyword
valand=and; - Variable
x - Expression
e: many forms of these, most containing subexpressions
syntax vs semantics
- Syntax is just how you write something
- Semantics is what that something means
- Type-checking (before program runs) : extend static environment
- Evaluation (as program runs) : extend dynamic environment ```ml val x = 42; (* type-checking : static env {x : int}
- evaluation : dynamic env {x : 42} *) ```
Expressions
- There are many kinds of expressions
- Expression can contain any subexpression…
- Precise definitions can predict complex programs
- Every kind of expression has
- Syntax
- Type-checking rules : produces a type
- Evaluation rules : produces a value after type-check
variables
- Syntax : sequence of letters, digits,
_, not starting with digit - Type-checking : look up type in current static environment
- Evaluation : look up value in current dynamic environment
Addition
- Syntax :
e1+e2wheree1ande2are expressions - Type-checking :
e1,e2, ande1 + e2must be of the same type(intorreal) - Evaluation : if
e1evaluates to v1 ande2evaluates to v2,e1 + e2evaluates to sum of v1 and v2
Values
- All values are expressions but the opposite is not
- 21, 99 have type int
- true, false have type bool
- () has type unit : it means nothing
- “string”, “str” have type string
- 3.14, 2.0 have type real
conditional expression
- Syntax : if
e1thene2elsee3 - Type-checking :
e1must have type boole2ande3must be of the same type but have any type- so, the type of the entire expression is also
e2,e3type
- Evaluation : evaluate
e1: true -> evaluatee2, false -> evaluatee2
less-than expression
- Syntax :
e1 < e2 - Type-checking :
e1ande2must be of the same type- the type of entire expression is bool
- Evaluation : evaluate
e1to v1 ande2to v2 and producetrueif v1 less than v2 elsefalse
function
It has arguments and result
(* `: type` can be omitted *)
fun pow (x : int, y : int) : int =
if y = 0
then 1
else x * pow(x, y-1)
(* val pow = fn : int * int -> int *)
- The use of
*in type syntax is not multiplication - Cannot refer to later function bindings
- So, helper functions must come before their uses
- Need special construct for mutual recursion
and
- use Recursion : that is more powerful than loops
- but sometimes loops are appropriate solutions
- functions can be passed as parameters of another function or returned from another function (First-class function)
function bindings
- Syntax : `fun x0 (x1 : t1, …, xn : tn) = e
- Evaluation : A FUNCTION IS A VALUE! (not evaluation)
- add
x0to dynamic env so later expressions can call it
- add
Type-checking
To type-check a function binding, we type-check the body e in a static environment that (in addition to all the earlier bindings) maps x1 to t1, … xn to tn (arguments) and x0 to t1 * ... * tn -> t (for recursion).
function calls
-Syntax : e0 (e1, ..., en)
* parentheses optional if there is only one argument
- Type-checking :
e0has some typet1 * ... * tn -> t,e1to t1, …ento tn => e0 (e1, …, en) has type t - Evaluation : extend dynamic environment
- evaluate
e0to a function x0 - evaluate arguments to values
- result is evaluation of e in an environment that is extended
- evaluate
comparisons
=(equal),<>(inequality) : can be used any “equality type” but not with real>,<,>=,<=: can be used with real