CS 541 Lecture -*- Outline -*-
* Name bindings statically scoped
objective: to get across the notions of:
sugars
simultaneous vs. sequential bindings,
scope
environment
** pattern matching in fun is sugar for case (p.112)
---------------
PATTERN SUGARS
fun fact 0 = 1
| fact n = n * fact(n-1);
(* equivalent to *)
fun fact x =
(case x of
0 => 1
| n => n * fact(n-1));
-----------------
discuss the meaning of the case,
pattern match from the top
** top-level binding: val (sections 2.1, 2.2)
val name = E
binds name to the value of E,
doesn't complain if name already has a binding
*** redefinition (sequential bindings)
---------------
SEQUENTIAL BINDINGS
- val x = 3;
val x = 3 : int
- val y = x + 1;
val y = 4 : int
- val x = x + 1;
val x = 5 : int
- x;
val it = 5 : int
-----------------
can be used for redefinition, redefinition useful for debugging
redefinition makes a new environment, old one still exists
val x = 3; global env --> [x: 3]
val x = 5; global env \ [x: 3]
\-> [x: 5]
--------------------------
- fun inc5(y) = y + x;
val inc5 = fn : int -> int
- val x = 7;
val x = 7 : int
- inc5(10);
val it = 15 : int
---------------------------
redefinition doesn't work like assignment from *inside* a program,
makes a new binding
instead of changing one in surrounding scope.
---------------------------------------
- fun foo() = let val x = 4 in x end;
val foo = fn : unit -> int
- foo();
val it = 4 : int
- x;
val it = 7 : int
-------------------------
this shows that val doesn't do asignment
*** simultaneous bindings
expressions on right all evaluated,
then bindings made simultaneously
---------------
SIMULTANEOUS BINDINGS
- val x = 3
and y = 4;
val x = 3 : int
val y = 4 : int
- val x = y
and y = x;
val x = 4 : int
val y = 3 : int
- val (x,y) = (y,x);
val x = 3 : int
val y = 4 : int
-----------------------------
the second one really gives the key idea:
evaluate the right hand sides, then bind
it's equivalent to the third
note this is the way to do mutual recursion too.
------------------------------
- fun odd(0) = false
| odd(n) = even(n - 1)
and even(0) = true
| even(n) = odd(n - 1);
val odd = fn : int -> bool
val even = fn : int -> bool
---------------
** program (nestable) forms
*** let
hides declarations within an expression
**** sequential bindings
let val x1 = e1 in E end
=def= ((fn x1 => E) e1)
--------------
LET EXPRESSIONS
- let val x = 3 in x+1 end;
val it = 4 : int
- ((fn x => x+1) 3);
val it = 4 : int
- let val x = 33 (* optional ; *)
val y = x + 2;
val z = y * x
in
z * z
end;
val it = 1334025 : int
--------------
let val x1 = e1
val x2 = e2
...
val xn = en
in E end
=def= let val x1 = e1
in let val x2 = e2
...
val xn = en
in E end
end
sequential binding of names
can use x1 in x2, etc.
Q: Can you use let to write a tail recursive version of member?
**** simultaneous bindings
----------------------------
let val x = 3 and y = 4
in let val y = x
and x = y
in [x,y]
end
end;
----------------------------
let val x1 = e1
and x2 = e2
...
and xn = en
in E end
=def= ((fn (x1,x2,...,xn) => E) (e1,e2,...,en))
simultaneous local binding of names
(note that the xi cannot be used in defining the other xj)
*work examples*
*** local
--------------------------
LOCAL vs. LET
let allows decls within expression
let val x = 3
in x * x * x
end;
local allows decls within decls
local val x = 3
in val twentyseven = x * x * x
end;
local val pi_over_4 = 3.14159/4.0
in fun cosine ang = ... pi_over_4 ...
end;
--------------------------
hides declarations in a declaration
see the book for details.
** Binding vs. assignment
*** references and assignment (chapter 8)
val x = ref 3;
now x has type: int ref
that is, x denotes a cell (location) that can be changed
x := e2
mutates the cell denoted by x.
x must be defined already
!x
gets value out of cell denoted by x
--------------
REFERENCES
- val x = ref 3;
val x = ref 3 : int ref
- x := 4;
val it = () : unit
- x;
val it = ref 4 : int ref
- !x;
val it = 4 : int
--------------
*** differences
let sets up a binding,
does not change existing bindings
=> referential transparency
:= makes assignment
no referential transparency
what's bound to what:
name bound to value, because 3 may be value of several names
the binding is a property of the name (not 3)