990 likes | 1.01k Views
Explicit State. Seif Haridi Peter Van Roy. Explicit State I. The box O. State as a group of memory cells. The box O can remember information between independent invocations, it has a memory The basic elements of explicit state Index datatypes
E N D
Explicit State Seif Haridi Peter Van Roy Seif Haridi and Peter Van Roy
Explicit State I The box O State as a group of memory cells • The box O can remember information between independent invocations, it has a memory • The basic elements of explicit state • Index datatypes • Basic techniques and ideas of using state in program design An Interface that hides the state Group of functions and procedures that operate on the state Seif Haridi and Peter Van Roy
Explicit State II The box O • What is the difference between implicit state and explicit state • What is the difference between state in general and encapsulated state • Component based programming and object-oriented programming • Data abstractions using encapsulated state State as a group of memory cells An Interface that hides the state Group of functions and procedures that operate on the state Seif Haridi and Peter Van Roy
What is state? • State is a sequence of values in time that contains the intermediate results of a desired computation • Declarative programs can also have state according to this definition • Consider the following program fun {Sum XsA} case Xs of X|Xr then {Sum XrA+X} [] nil then A end end {Show {Sum [1 2 3 4] 0}} Seif Haridi and Peter Van Roy
What is implicit state? The two arguments Xs and A represent an implicit state Xs A [1 2 3 4] 0 [2 3 4] 1 [3 4] 3 [4] 6 nil 10 fun {Sum XsA} case Xs of X|Xr then {Sum XrA+X} [] nil then A end end {Show {Sum [1 2 3 4] 0}} Seif Haridi and Peter Van Roy
What is explicit state: Example? An unbound variable X C A cell C is created with initial value 5 X is bound to C 5 X C The cell C, which X is bound to, is assigned the value 6 6 X Seif Haridi and Peter Van Roy
What is explicit state: Example? An unbound variable X • The cell is a value container with a unique identity • X is really bound to the identity of the cell • When the cell is assigned, X does not • change C A cell C is created with initialvalue 5 X is bound to C 5 X C The cell C, which X is bound to, is assigned the value 6 6 X Seif Haridi and Peter Van Roy
What is explicit state? • X = {NewCell I} • Creates a cell with initial value I • Binds X to the identity of the cell • Example: X = {NewCell 0} • X:=J • Assumes X is bound to a cell C (otherwise exception) • Changes the content of C to become J • Y = @X • Assumes X is bound to a cell C (otherwise exception) • Binds Y to the value contained in C Seif Haridi and Peter Van Roy
Examples 0 X • X = {NewCell 0} • X:=5 • Y = X • Y:=10 • @X == 10 % returns true • X == Y% returns true 5 X Y 10 X Y Seif Haridi and Peter Van Roy
Examples 10 X • X = {NewCell 10}Y = {NewCell 10} • X == Y% returns false • Because X and Y refer to different cells, with different identities • @X == @Y % returns true 10 Y Seif Haridi and Peter Van Roy
Examples 0 X • X = {NewCell 0} • X:=5 • Y = X • Y:=10 • @X == 10returns true 5 X Y 10 X Y Seif Haridi and Peter Van Roy
The model extended with cells Semantic stack (Thread 1) Semantic stack (Thread n) ..... w= f(x) z = person(a:y) y = 1 u = 2 x 1: w 2: x .... .... single assignment store mutable store Seif Haridi and Peter Van Roy
The stateful model s::= skip empty statement|s1s2statement sequence | ... |threads1 end thread creation|{NewCellxc}cell creation |{Exchange cx y} cell exchange Exchange: bind xto the old content of cand set the content of the cell cto y Seif Haridi and Peter Van Roy
The stateful model |{NewCellxc}cell creation |{Exchange cx y} cell exchange Exchange: bind xto the old content of cand set the content of the cell cto y proc {Assign C X} {Exchange C _ X} end fun {Access C} X in{Exchange C X X}X end The ’@’ and ’:=’ syntaxes are syntactic sugar for Assign and Access Seif Haridi and Peter Van Roy
Do we need explicit state? • Up to now the computation model we introduced in the previous lectures did not have any notion of explicit state • And important question is: do we need explicit state? • There is a number of reasons for introducing state. We discuss them some of them here Seif Haridi and Peter Van Roy
Programs that changetheir behavior over time • Declarative program: all information is in the arguments • Stateful program: new information can be put inside a running program Program Program Seif Haridi and Peter Van Roy
Modular programs • A system (program) is modular if changes (updates) in the program are confined to the components where the functionality are changed • Here is an example where introduction of explicit state in a well confined way leads to program modularity compared to programs that are written using only the declarative model (where evey component is a function) Seif Haridi and Peter Van Roy
Encapsulated state I fun {MF} fun {F ...} Definition of F endfun {G ...} Definition of G end in ’export’(f:F g:G) end M = {MF} • Assume we have three persons, P, U1, and U2 • P is a programmer who developed a component M that provides two functions F and G • U1 and U2 are system builders that use the component M Seif Haridi and Peter Van Roy
Encapsulated state I • Assume we have three persons, P, U1, and U2 • P is a programmer who developed a component M that provides two functions F and G • U1 and U2 are system builders that use the component M functor MF export f:F g:G define fun {F ...} Definition of F end fun {G ...} Definition of G end end Seif Haridi and Peter Van Roy
Encapsulated state II • User U2 has a demanding application • He wants to extend the module M to enable him to monitor how many times the function F is invoked in his application • He goes to P, and asks him to do so without changing the interface to M fun {M} fun {F ...} Definition of F endfun {G ...} Definition of G end in ’export’(f:F g:G) end Seif Haridi and Peter Van Roy
Encapsulated state III • This cannot be done in the declarative model because F cannot remember its previous invocations • The only way is to change the interface to F by adding two extra arguments FIn and FOut: fun {F ... +FIn ?FOut} FOut = FIn+1 ...end • The rest of the program always remembers the previous number of invocations (FIn), and FOut returns the new number of invocations • But this changes the interface! Seif Haridi and Peter Van Roy
Encapsulated state III fun {MF} X = {NewCell 0} fun {F ...} X:=@X+1 Definition of F endfun {G ...} Definition of G end fun {Count} @X end in ’export’(f:F g:G c:Count) end M = {MF} • A cell is created when MF is called • Due to lexical scoping the cell is only visible to the created version of F and Count • The M.f did not change • New function M.c is available • X is hidden: only visible inside M (encapsulated state) Seif Haridi and Peter Van Roy
Relationship between the declarative model and the stateful model • Declarative programming guarantees by construction that each procedure computes a function • This means each component (and subcomponent) is a function • It is possible to use encapsulated state (cells) so that a component is declarative from outside, and stateful from the inside • Considered as a black-box the program procedure is still a function Seif Haridi and Peter Van Roy
Programs with accumulators local fun {Sum1 Xs A} case Xs of X|Xr then {Sum1 Xr A+X} [] nil then A endend in fun {Sum Xs} {Sum1 Xs 0} end Seif Haridi and Peter Van Roy
Programs with accumulators fun {Sum Xs} fun {Sum1 Xs} case Xs of X|Xr thenA:=X+@A{Sum1 Xr} [] nil then{Access A} endendA = {NewCell 0} in {Sum1 Xs} end fun {Sum Xs} fun {Sum1 Xs A} case Xs of X|Xr then {Sum1 Xr A+X} [] nil thenA endend in {Sum1 Xs 0} end Seif Haridi and Peter Van Roy
Programs with accumulators fun {Sum Xs} fun {Sum1 Xs} case Xs of X|Xr thenA:=X+@A{Sum1 Xr} [] nil then@A endendA = {NewCell 0} in {Sum1 Xs} end fun {Sum Xs} A = {NewCell 0} in {ForAll Xs proc {$ X} A:=X+@A end}@A end Seif Haridi and Peter Van Roy
Programs with accumulators fun {Sum Xs} A = {NewCell 0} in {ForAll Xs proc {$ X} A:=X+@A end}@A end fun {Sum Xs} A = {NewCell 0} in for X in Xs do A:=X+@A end@A end The state is encapsulated inside each procedure invocation Seif Haridi and Peter Van Roy
Data abstraction (revisited) • With encapsulated state, we can complete the discussion started in Chapter 4 • For a given functionality, there are many ways to package the data abstraction. We distinguish three axes. • Open vs. secure: is the internal representation visible to the program or hidden? • Declarative vs. stateful: does the data abstraction have encapsulated state or not? • Bundled vs. unbundled: is the data kept together from the operations or is it separable? • Let us see what our stack abstraction looks like with some of these possibilities Seif Haridi and Peter Van Roy
Stack:Open, declarative, and unbundled • Here is the basic stack, as we saw it before:fun {NewStack} nil endfun {Push S E} E|S endfun {Pop S E} case S of X|S1 then E=X S1 end endfun {IsEmpty S} S==nil end • This is completely unprotected. Where is it useful? Primarily, in small programs in which expressiveness is more important than security. Seif Haridi and Peter Van Roy
Stack:Secure, declarative, and unbundled • We can make the declarative stack secure by using a wrapper:local Wrap Unwrapin {NewWrapper Wrap Unwrap}fun {NewStack} {Wrap nil} endfun {Push S E} {Wrap E|{Unwrap S}}endfun {Pop S E} case{Unwrap S}of X|S1 then E=X {Wrap S1}end endfun {IsEmpty S} {Unwrap S} ==nil endend • Where is this useful? In large programs where we want to protect the implementation of a declarative component. Seif Haridi and Peter Van Roy
Stack:Secure, stateful, and bundled • This is the simplest way to make a secure stateful stack:proc {NewStack Push Pop IsEmpty} C={NewCell nil}inproc {Push X} C:=X|@Cendfun {Pop} case@Cof X|S then C:=S X end endfun {IsEmpty C} @C==nil endend • Compare the declarative with the stateful versions: the declarative version needs two arguments per operation, the stateful version uses higher-order programming (instantiation) • With some syntactic support, this gives object-oriented programming Seif Haridi and Peter Van Roy
Stack:Secure, stateful, and unbundled • Let us combine the wrapper with state:local Wrap Unwrapin {NewWrapper Wrap Unwrap}fun {NewStack} {Wrap {NewCell nil}}endproc {Push W X} C={Unwrap W} inC:=X|@C endfun {Pop W} C={Unwrap W} incase @C of X|S then C:=S X endendfun {IsEmpty S} @ {Unwrap W}==nil endend • This version is stateful but lets us store the stack separate from the operations. The same operations work on all stacks. Seif Haridi and Peter Van Roy
Some ways to package a stack • Open, declarative, and unbundled: the usual declarative style, e.g., as in Prolog and Scheme • Secure, declarative, and unbundled: use wrappers to make the declarative style secure • Secure, stateful, and bundled: the usual object-oriented style, e.g., as in Smalltalk and Java • Secure, stateful, and unbundled: an interesting variation on the usual object-oriented style • Other possibilities: there are four more possibilities! Try to write all of them. Seif Haridi and Peter Van Roy
Indexed Collections • Indexed collections groups a set of (partial) values • The individual elements are accessible through an index • The declarative model provides: • tuples, e.g. date(17 december 2001) • records, e.g. date(day:17 month:decemeber year:2001) • We can now add state to the fields • arrays • dictionaries Seif Haridi and Peter Van Roy
Arrays • An array is a mapping from integers to (partial) values • The domain is a set of consecutive integers, with a lower bound and an upper bound • The range can be mutated (change) • A good approximation is to thing of arrays as a tuple of cells Seif Haridi and Peter Van Roy
Operations on arrays • A = {Array.new LBUB?Value} • Creates an array A with lower bound LB and upper bound UB • All elements are initialized to Value • There are other operations: • To access and update the elements of the array • Get the lower and upper bounds • Convert an array to tuple and vice versa • Check its type Seif Haridi and Peter Van Roy
Example 1 fun {MakeArray L H F} A = {Array.new L H unit} in for I in L..H do A.I := {F I} end A end • A = {MakeArray L H F} • Creates an array A where for each index I is mapped to {F I} Seif Haridi and Peter Van Roy
Array2Record • R = {Array2Record L A} • Define a function that takes a label L and an array A, it returns a record R whose label is L and whose features are from the lower bound of A to the upper bound of A • We need to know how to make a record • R = {Record.make L Fs} • creates a record R with label L and a list of features (selector names), returns a record with distict fresh variables as values • L = {Array.low A} and H = {Array.high A} • Return lower bound and higher bound of array A Seif Haridi and Peter Van Roy
Array2Record fun {Array2Record LA A} L = {Array.low A} H = {Array.high A} R = {Record.make LA {From L H}} in for I in L..H do R.I = A.I end R end Seif Haridi and Peter Van Roy
Tuple to Array fun {Tuple2Array T} H = {Width T} in {MakeArray 1 H fun{$ I} T.I end} end Seif Haridi and Peter Van Roy
Dictionaries (Hash tables) • A dictionary is a mapping from simple values or literals (integers, atoms, amd names) to (partial) values • Both the domain and the range can be mutated (changed) • The pair consisting of the literal and the value is called an item • Items can be added, changed and removed in amortized constant time • That is to say n operations takes on average O(n) Seif Haridi and Peter Van Roy
Operations on dictionaries • D = {Dictionary.new} • Creates an empty dictionary • There are other operations: • To access and update (and add) the elements of a dictionary using the ’.’ and ’:=’ notations • Remove an item, test the memership of a key • Convert a dictionary to a record and vice versa • Check its type Seif Haridi and Peter Van Roy
Indexed Collections stateless collection Tuple Add state Add atoms as indices stateful collection Array Record Add atoms as indices Add state Dictionary Seif Haridi and Peter Van Roy
Other collections stateless collection lists potentially infinite lists ports streams stateful collection generalizes streams to stateful mailboxes stacks queues stateless Seif Haridi and Peter Van Roy
Encapsulated statefulabstract datatypes • These are stateful entities that can be access only by the external interface • The implementation is not visible outside • The are two method to build stateful abstract data types • The functor based approach (record interface) • The procedure dispatch approach Seif Haridi and Peter Van Roy
The functor-based approach fun {NewCounter I} S = {Record.toDictionary state(v:I)} proc {Inc}S.v := S.v + 1end proc {Dec}S.v := S.v – 1end fun {Get} S.v end proc {Put I} S.v := I end proc {Display} {Show S.v} end ino(inc:Incdec:Decget:Getput:Putshow:Display) end Seif Haridi and Peter Van Roy
The functor-based approach fun {NewCounter I} S = {Record.toDictionary state(v:I)} proc {Inc}S.v := S.v + 1end proc {Dec}S.v := S.v – 1end fun {Get} S.v end proc {Put I} S.v := I end proc {Display} {Show S.v} end ino(inc:Incdec:Decget:Getput:Putshow:Display) end The state is collected in dictionary S The state is completely encapsulated i.e. not visible out side Seif Haridi and Peter Van Roy
The functor-based approach fun {NewCounter I} S = {Record.toDictionary state(v:I)} proc {Inc}S.v := S.v + 1end proc {Dec}S.v := S.v – 1end fun {Get} S.v end proc {Put I} S.v := I end proc {Display} {Show S.v} end ino(inc:Incdec:Decget:Getput:Putshow:Display) end The interface is created for each instance Counter Seif Haridi and Peter Van Roy
The functor-based approach fun {NewCounter I} S = {Record.toDictionary state(v:I)} proc {Inc}S.v := S.v + 1end proc {Dec}S.v := S.v – 1end fun {Get} S.v end proc {Put I} S.v := I end proc {Display} {Show S.v} end ino(inc:Incdec:Decget:Getput:Putshow:Display) end function that access the state by lexical scope Seif Haridi and Peter Van Roy
Call pattern declare C1 C2 C1 = {NewCounter 0} C2 = {NewCounter 100} {C1.inc} {C1.show} {C2.dec} {C2.show} Seif Haridi and Peter Van Roy