Seif Haridi and Peter Van Roy1 Explicit State Seif Haridi Peter Van Roy.
Post on 19-Dec-2015
219 Views
Preview:
Transcript
Seif Haridi and Peter Van Roy 1
Explicit State
Seif Haridi
Peter Van Roy
Seif Haridi and Peter Van Roy 2
Explicit State I
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
Group of functions and procedures that operateon the state
An Interface that hidesthe state
The box O
Seif Haridi and Peter Van Roy 3
Explicit State II
State as a group of memory cells
• 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
Group of functions and procedures that operateon the state
An Interface that hidesthe state
The box O
Seif Haridi and Peter Van Roy 4
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 Xs A} case Xs of X|Xr then {Sum Xr A+X} [] nil then A end end
{Show {Sum [1 2 3 4] 0}}
Seif Haridi and Peter Van Roy 5
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 Xs A} case Xs of X|Xr then {Sum Xr A+X} [] nil then A end end
{Show {Sum [1 2 3 4] 0}}
Seif Haridi and Peter Van Roy 6
What is explicit state: Example?
XAn unboundvariable
XA cell C is created with initial value 5X is bound to C
5
XThe cell C, which X is bound to, is assigned the value 6
6
C
C
Seif Haridi and Peter Van Roy 7
What is explicit state: Example?
XAn unboundvariable
XA cell C is created with initialvalue 5X is bound to C
5
XThe cell C, which X is bound to, is assigned the value 6
6
C
C
• 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 notchange
Seif Haridi and Peter Van Roy 8
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 9
Examples• X = {NewCell 0}
• X:=5
• Y = X
• Y:=10
• @X == 10 % returns true
• X == Y % returns true
X 0
X 5
Y
X 10
Y
Seif Haridi and Peter Van Roy 10
Examples• 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
X 10
Y 10
Seif Haridi and Peter Van Roy 11
Examples
• X = {NewCell 0}
• X:=5
• Y = X
• Y:=10
• @X == 10returns true
X 0
X 5
Y
X 10
Y
Seif Haridi and Peter Van Roy 12
The model extended with cells
Semantic stack(Thread 1)
Semantic stack(Thread n)
w = f(x)z = person(a:y)y = 1u = 2x
1: w2: x........
.....
single assignmentstore
mutable store
Seif Haridi and Peter Van Roy 13
The stateful model
s::= skip empty statement| s1 s2 statement sequence
| ... | thread s1 end thread creation| {NewCell x c} cell creation| {Exchange c x y} cell exchange
Exchange: bind x to the old content of c and set thecontent of the cell c to y
Seif Haridi and Peter Van Roy 14
The stateful model
| {NewCell x c} cell creation| {Exchange c x y} cell exchange
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
Exchange: bind x to the old content of c and set thecontent of the cell c to y
Seif Haridi and Peter Van Roy 15
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 16
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 17
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 18
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
fun {MF}fun {F ...} Definition of Fendfun {G ...} Definition of Gend
in ’export’(f:F g:G)endM = {MF}
Seif Haridi and Peter Van Roy 19
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 MFexport f:F g:Gdefine fun {F ...} Definition of F end fun {G ...} Definition of G endend
Seif Haridi and Peter Van Roy 20
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 Fendfun {G ...} Definition of Gend
in ’export’(f:F g:G)
end
Seif Haridi and Peter Van Roy 21
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 22
fun {MF}X = {NewCell 0}
fun {F ...} X:=@X+1
Definition of Fendfun {G ...} Definition of G endfun {Count} @X end
in ’export’(f:F g:G c:Count)endM = {MF}
Encapsulated state III
• 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 23
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 24
Programs with accumulators
localfun {Sum1 Xs A}
case Xs of X|Xr then {Sum1 Xr A+X} [] nil then A end
endin fun {Sum Xs} {Sum1 Xs 0} end
Seif Haridi and Peter Van Roy 25
Programs with accumulators
fun {Sum Xs}fun {Sum1 Xs A}
case Xs of X|Xr then {Sum1 Xr A+X} [] nil then A end
endin {Sum1 Xs 0} end
fun {Sum Xs}fun {Sum1 Xs}
case Xs of X|Xr then
A:=X+@A{Sum1 Xr}
[] nil then {Access A} end
end A = {NewCell 0}
in {Sum1 Xs} end
Seif Haridi and Peter Van Roy 26
Programs with accumulators
fun {Sum Xs}fun {Sum1 Xs}
case Xs of X|Xr then
A:=X+@A {Sum1 Xr}
[] nil then @A end
end A = {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 27
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}
infor X in Xs do A:=X+@A end@A
endThe state is encapsulated inside each procedure invocation
Seif Haridi and Peter Van Roy 28
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 29
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 30
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 end
end
• Where is this useful? In large programs where we want to protect the implementation of a declarative component.
Seif Haridi and Peter Van Roy 31
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|@C endfun {Pop} case @C of X|S then C:=S X end endfun {IsEmpty C} @C==nil end
end• 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 32
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} in C:=X|@C endfun {Pop W} C={Unwrap W} in
case @C of X|S then C:=S X endendfun {IsEmpty S} @ {Unwrap W}==nil end
end• 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 33
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 34
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 35
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 36
Operations on arrays
• A = {Array.new LB UB ?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 37
Example 1
• A = {MakeArray L H F}
• Creates an array A where for each index I is mapped to {F I}
fun {MakeArray L H F} A = {Array.new L H unit}in for I in L..H do A.I := {F I} end Aend
Seif Haridi and Peter Van Roy 38
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 39
Array2Recordfun {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 Rend
Seif Haridi and Peter Van Roy 40
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 41
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 42
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 43
Indexed Collections
Tuple
Array Record
Dictionary
Add state Add atoms as indices
Add stateAdd atoms as indices
stateless collection
stateful collection
Seif Haridi and Peter Van Roy 44
Other collections
lists
streams
stacks
queues
potentiallyinfinite lists
stateless
ports
generalizesstreams to statefulmailboxes
stateless collection
stateful collection
Seif Haridi and Peter Van Roy 45
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 46
The functor-based approach
fun {NewCounter I}
SS = {Record.toDictionary state(v:I)}
proc {Inc} S.v := S.v + 1 end
proc {Dec} S.v := S.v – 1 end
fun {Get} S.v end
proc {Put I} S.v := I end
proc {Display} {Show S.v} end
in o(inc:Inc dec:Dec get:Get put:Put show:Display)
end
Seif Haridi and Peter Van Roy 47
The functor-based approach
fun {NewCounter I}
SS = {Record.toDictionary state(v:I)}
proc {Inc} S.v := S.v + 1 end
proc {Dec} S.v := S.v – 1 end
fun {Get} S.v end
proc {Put I} S.v := I end
proc {Display} {Show S.v} end
in o(inc:Inc dec:Dec get:Get put:Put show:Display)
end
The state is collected in dictionary SThe state is completely encapsulatedi.e. not visible out side
Seif Haridi and Peter Van Roy 48
The functor-based approach
fun {NewCounter I}
SS = {Record.toDictionary state(v:I)}
proc {Inc} S.v := S.v + 1 end
proc {Dec} S.v := S.v – 1 end
fun {Get} S.v end
proc {Put I} S.v := I end
proc {Display} {Show S.v} end
in o(inc:Inc dec:Dec get:Get put:Put show:Display)
end
The interface is created for eachinstance Counter
Seif Haridi and Peter Van Roy 49
fun {NewCounter I}
SS = {Record.toDictionary state(v:I)}
proc {Inc} S.v := S.v + 1 end
proc {Dec} S.v := S.v – 1 end
fun {Get} S.v end
proc {Put I} S.v := I end
proc {Display} {Show S.v} end
in o(inc:Inc dec:Dec get:Get put:Put show:Display)
end
The functor-based approach
function that accessthe state by lexical scope
Seif Haridi and Peter Van Roy 50
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 51
Defined as a functor
functor Counter
export inc:Inc dec:Dec get:Get put:Put show:Display init:Init
define
SS
proc {Init init(I)} SS = {Record.toDictionary state(v:I)} end
proc {Inc} S.v := S.v + 1 end
proc {Dec} S.v := S.v – 1 end
fun {Get} S.v end
proc {Put I} S.v := I end
proc {Display} {Show S.v} end
end
Seif Haridi and Peter Van Roy 52
Functors
• Functors have been used as a specification of modules
• Also functors have been used as a specification of abstract datatypes
• How to create a stateful entity from a functor?
Seif Haridi and Peter Van Roy 53
Explicit creation of objects from functors
• Given a variable F that is bound to a functor
• [O] = {Module.apply [F]}creates stateful ADT object O that is an instance of F
• Given the functor F is stored on a file ’f.ozf’
• [O] = {Module.link [’f.ozf’]}creates stateful ADT object O that is an instance of F
Seif Haridi and Peter Van Roy 54
Defined as a functor
functor Counter
export inc:Inc dec:Dec get:Get put:Put show:Display init:Init
define
SS
proc {Init init(I)} SS = {Record.toDictionary state(v:I)} end
proc {Inc} S.v := S.v + 1 end
proc {Dec} S.v := S.v – 1 end
fun {Get} S.v end
proc {Put I} S.v := I end
proc {Display} {Show S.v} end
end
Seif Haridi and Peter Van Roy 55
Pattern of use
fun {New Functor Init}
[M] = {Module.apply [Functor]}
{M.init Init}
M
end
declare C1 C2
C1 = {New Counter init(0)}
{C1.inc} {C1.show}
{C2.inc} {C2.show}
Seif Haridi and Peter Van Roy 56
Example: memoization
• Stateful programming can be used to speed up declarative (functional) components by remembering previous results
• Consider Pascal’s triangle
• One way to make it faster between separate invocations is to remember previously computed rows
• Here follow our principle and change only the internals of a component
Seif Haridi and Peter Van Roy 57
Functions over lists
• Compute the function {Pascal N}
• Takes an integer N, and returns the Nth row of a Pascal triangle as a list
1. For row 1, the result is [1]
2. For row N, shift to left row N-1 and shift to the right row N-1
3. Align and add the shifted rows element-wise to get row N
111
1 2 1
1 3 3 1
1 4 6 4 1
(0) (0)
[0 1 3 3 1]
[1 3 3 1 0]
Shift right
Shift left
Seif Haridi and Peter Van Roy 58
fun {FastPascal N} if N==1 then [1] else local L in
L={FastPascal N-1} {AddList {ShiftLeft L} {ShiftRight L}}end
endend
Faster Pascal
• Introduce a local variable L
• Compute {FastPascal N-1} only once
• Try with 30 rows.
• FastPascal is called N times, each time a list on the average of size N/2 is processed
• The time complexity is proportional to N2 (polynomial)
• Low order polynomial programs are practical.
Seif Haridi and Peter Van Roy 59
Memoizing FastPascal• {FastPascal N} New Version
1. Make a store S available to FastPascal
2. Let K be the number of the rows stored in S (i.e. max row is the Kth row)
3. if N is less or equal K retrieve the Nth row from S
4. Otherwise, compute the rows numbered K+1 to N, and store them in S
5. Return the Nth row from S
• Viewed from outside (as a black box), this version behaves like the earlier one but faster
declare[S] = {Module.apply [StoreFun]}{S.put 2 [1 1]} {Browse {Get S 2}}{Browse {Size S}}
(see the program)
Seif Haridi and Peter Van Roy 60
The store functorfunctorexport put:Put get:Get size:Sizedefine S = {NewDictionary} C = {NewCell 0} proc {Put K X} if {Not {Dictionary.member S K}} then
C:=@C+1 end S.K := X end fun {Get K} S.K end fun {Size} @C endend
Seif Haridi and Peter Van Roy 61
The Pascal functor
functor PascalFun
import S at 'Store.ozf’ System
export
pascal:FastPascal
define
fun {FastPascal N} Definition of Pascal end
Definition of help procedures for Pascal {S.put 1 [1]}
end
Seif Haridi and Peter Van Roy 62
Memo Pascal (1) fun {FastPascal N} MaxRow in MaxRow = {S.size} if N =< MaxRow then
{S.get N} else L in
Compute the next N-MaxRow rows stating from row the value of MaxRow, call this list of rows L {PutList S MaxRow+1 L} {S.get N}
end end
Seif Haridi and Peter Van Roy 63
Memo Pascal (2) fun {FastPascal N} MaxRow in MaxRow = {S.size} if N =< MaxRow then
{S.get N} else L in
L = {PascalListNext N-MaxRow {S.get MaxRow}} {PutList S MaxRow+1 L} {S.get N}
end end
Seif Haridi and Peter Van Roy 64
The procedure dispatch approach
• Another method to realize stateful data abstractions is the procedure dispatch approach
• The instance of the data abstraction is a one argument procedure
• The procedure receives messages (when called) • and dispatches to the right function according to the label
of the message• State is encapsulated• The interface is defined as messages (implemented as
records)
Seif Haridi and Peter Van Roy 65
The procedure-based approach
fun {NewCounter I}
SS = {Record.toDictionary state(v:I)}
proc {Inc inc} S.v := S.v + 1 end
proc {Dec dec} S.v := S.v – 1 end
proc{Get get(I)} I = S.v end
proc {Put put(I)} S.v := I end
proc {Display show} {Show S.v} end
D = o(inc:Inc dec:Dec get:Get put:Put show:Display)
in proc{$ M} {D.{Label M} M} end
end
Seif Haridi and Peter Van Roy 66
Call pattern
declare C1 C2C1 = {NewCounter 0}C2 = {NewCounter 100}
{C1 put(10)} {C1 inc} declare X {C1 get(X)}{C1 show}
{C2 dec}{C2 show}
Seif Haridi and Peter Van Roy 67
Declarative vs. Stateful
• We are going to study two different implementations of an algorithm, one using a stateful data type representation and the other using a stateless representation
• The stateful representation will lead to a stateful (imperative) algorithm
• The stateless representation will lead to a declarative (functional) algorithm
• We start from the abstract description of the algorithm
• Which approach is better? We will see!
Seif Haridi and Peter Van Roy 68
Transitive closure
• A directed graph consists of a set of vertices (nodes) V and a set of edges (represented as set of pairs of vertices) E
• (vi,vj) E iff there is an edge from vi to vj
2
1
4
3
65
{1,2,3,4,5,6}
{(1,2), (2,3), (3,4), (4,5), (5,6),(6,2) (1,2) }
The vertices
The edges
Seif Haridi and Peter Van Roy 69
Transitive closure
• Calculate a new graph TG, from the original graph G such that TG is the transitive closure of G
• That is to say there is an edge between a pair of nodes (i,j) in TG iff there is a path from i to j in the graph G
Seif Haridi and Peter Van Roy 70
Transitive closure
1
4
3
65
2
The set of immediate predecessors on node I, Pred(I)The set of immediate successors on node I, Suc(I)
Pred(2) = {1 6 5}Suc(2) = {3}
Seif Haridi and Peter Van Roy 71
The algorithm works by transforming the graph incrementally
1
4
3
65
21
4
3
65
2
Seif Haridi and Peter Van Roy 72
The algorithm works by transforming the graph incrementally
1
4
3
65
21
4
3
6
5
2
Seif Haridi and Peter Van Roy 73
The abstract algorithm
• For each node x in the graph G
– For each node y in Pred(x)
• For each node z in Suc(x) add the edge (y,z) to G
Seif Haridi and Peter Van Roy 74
The representation
• The representation determines very much the model of implementation
• List (tree) based representation is suitable for a declarative formulation
• Array (dictionary) based representation is suitable for a stateful formulation
Seif Haridi and Peter Van Roy 75
Representation
• The adjacency list representation
• The graph is a list of elements of the form I#Ns
• I is the node identifier, Ns is the list of successor nodes
• The matrix representation
• The graph is a two dimensional array GM where GM.I.J is true iff there is an edge from node I to node J
Seif Haridi and Peter Van Roy 76
Transitive closure
• The matrix representation• M is the matrix
K
IJ
M.I.K = true
L
M.K.J = trueM.L.K = false
Seif Haridi and Peter Van Roy 77
From abstract to concreteMatrix representation
• For each node K in the graph G
– For each node I in Pred(K)
• For each node J in Suc(K) add the edge (I,J) to G
proc {StateTrans GM}
L={Array.low GM}
H={Array.high GM}
in
for K in L..H do
For each in I in Pred(K) For each J in Suc(K) add GM.I.J := true
end
end
Seif Haridi and Peter Van Roy 78
From abstract to concreteMatrix representation
• For each node K in the graph G
– For each node I in Pred(K)
• For each node J in Suc(K) add the edge (I,J) to G
proc {StateTrans GM}
L={Array.low GM}
H={Array.high GM}
in
for K in L..H do
for I in L..H do if GM.I.K then
For each J in Suc(K) add GM.I.J := true end
end
end
Seif Haridi and Peter Van Roy 79
From abstract to concreteMatrix representation
proc {StateTrans GM}
L H ... in
for K in L..H do
for I in L..H do if GM.I.K then for J in L..H do if GM.K.J then GM.I.J := true
endend
end %% if
end %% for
end %% for
end
proc {StateTrans GM}
L={Array.low GM}
H={Array.high GM}
in
for K in L..H do
for I in L..H do if GM.I.K then
For each J in Suc(K) add GM.I.J := true end
end
end
Seif Haridi and Peter Van Roy 80
From abstract to concreteMatrix representation
proc {StateTrans GM}
L H ... in
for K in L..H do
for I in L..H do if GM.I.K then for J in L..H do if GM.K.J then GM.I.J := true
endend
end %% if
end %% for
end %% for
end
proc {StateTrans GM}
L={Array.low GM}
H={Array.high GM}
in
for K in L..H do
for I in L..H do if GM.I.K then
For each J in Suc(K) add GM.I.J := true end
end
end
Seif Haridi and Peter Van Roy 81
From abstract to concreteMatrix representation
proc {StateTrans GM}
L H ... in
for K in L..H do
for I in L..H do if GM.I.K then for J in L..H do if GM.K.J then GM.I.J := true
endend
end %% if
end %% for
end %% for
end
proc {StateTrans GM}
L H ... in
for K in L..H do
for I in L..H do if GM.I.K then for J in L..H do GM.I.J := GM.I.J orelse GM.K.J end end %% if
end %% for
end %% for
end
Seif Haridi and Peter Van Roy 82
Transitive closureadjacency lists
1
4
3
65
2
[ 1 # [2] 2 # [1 3] 3 # [4] 4 # [5] 5 # [2] 6 # [2]]
The immediate successor list is sorted,e.g. 2 # [1 3]
Seif Haridi and Peter Van Roy 83
From abstract to concreteAdjacency list representation
• For each node X in the graph G
– For each node Y in Pred(X)
• For each node Z in Suc(X) add the edge (Y,Z) to G
fun {DeclTrans G}
Xs = {Nodes G} in
{FoldL Xs fun {$ InG X}
SX = {Suc X} For each node Y in Pred(X)
For each Z in SX add edge (Y,Z)
end
G}
end
G0, {F G0 X0} , {F {F G0 X0} X1}, ...
This is {FoldL Xs F G0}
Seif Haridi and Peter Van Roy 84
From abstract to concreteAdjacency list representation
fun {IncPath X SX InG}
{Map InG
fun{$ Y#SY}
Y#If Y in Pred(X) then
{Union SY SX} else SY end
end}
end
fun {DeclTrans G}
Xs = {Nodes G} in
{FoldL Xs fun {$ InG X}
SX = {Suc X} For each node Y in Pred(X)
For each Z in SX add edge (Y,Z) in GC
end
G}
end
For each node Y in PX For each Z in SX add
edge (Y,Z) in GC
Seif Haridi and Peter Van Roy 85
From abstract to concreteAdjacency list representation
fun {IncPath X SX InG}
{Map InG
fun{$ Y#SY}
Y#If {Member X SY} then
{Union SY SX} else SY end
end}
end
fun {DeclTrans G}
Xs = {Nodes G} in
{FoldL Xs fun {$ InG X}
SX = {Suc X} For each node Y in Pred(X)
For each Z in SX add edge (Y,Z) in GC
end
G}
end
Y in Pred(X) if and only if X in Pred(Y)
Seif Haridi and Peter Van Roy 86
Conclusion
• The stateful algorithm was straightforward in this case• The declarative algorithm was a bit harder• Both algorithms are of O(n3)• In the declarative algorithm we assume Successor list is
sorted• Union is just implemented by mergeing sorted lists O(n)• We exploited the fact that Y in Pred(X) if and only if X in
Pred(Y)
• The declarative one is better if the graph is sparse (many elements in the martix are ’false’)
Seif Haridi and Peter Van Roy 87
System building
• Abstraction is the best tool to build complex system
• Complex systems are built by layers of abstractions
• Each layer have to parts:
– Specification, and
– Implementation
• Any layer uses the specification of the lower layer to implement its functionality
Seif Haridi and Peter Van Roy 88
Properties needed to support the principle of abstraction
• Encapsulation
– Hide internals from the interface
• Compositionality
– Combine parts to make new parts
• Instantiation/invocation
– Create new instances of parts
Seif Haridi and Peter Van Roy 89
Component base programming
• Supports
– Encapsulation
– Compositionality
– Instantiation
Seif Haridi and Peter Van Roy 90
Object-oriented programming
• Supports
– Encapsulation
– Compositionality
– Instantiation
• Plus
– Inheritance
Seif Haridi and Peter Van Roy 91
Component-based programming
• ”Good software is good in the large and in the small, in its high level architecture and in its low-level details”. In Object-oriented software construction by Bertrand Meyer
• What is the best way to build big applications?
• A large application is (almost) always built by a team
• How should the team members communicate?
• This depends on the application’s structure (architecture)
• One way is to structure the application as a hierarchical graph
Seif Haridi and Peter Van Roy 92
Component-based programming
Interface
Component instance
Externalworld
Seif Haridi and Peter Van Roy 93
Component based design
• Team members are assigned individual components
• Team members communicate at the interface
• A component, can be implemented as a record that has a name, and a list of other component instances it needs, and a higher-order procedure that returns a component instance with the component instances it needs
• A component instance has an interface and an internal entities that serves the interface
Seif Haridi and Peter Van Roy 94
Model independence priciple
• As the system evolves, a component implementation might change or even the model changes– declarative (functional)– stateful sequential– concurrent, or– relational
• The interface of a component should be independent of the computation model used to implement the component
• The interface should depend only on the externally visible functionality of the component
Seif Haridi and Peter Van Roy 95
Example:memoization
• Consider Pascal’s triangle
• One way to make it faster between separate invocations is to remember previously computed rows
• Here we follow our principle and change only the internals of a component
Seif Haridi and Peter Van Roy 96
What happens at the interface?
• The power of the component based infrastructure depends on large extent on the expressiveness of the interface
• How does components communicate with each others?
• We have three possible case:
– The components are written in the same language
– The components are written in different languages
– The components are written in different computation model
Seif Haridi and Peter Van Roy 97
Components in the same language
• This is easy
• In Mozart/Oz component instances are modules (records whose fields contain the various services provided by the component-instance part
• In Java, interfaces are provided by objects (method invocations of objects)
• In Erlang, component instances are mainly concurrent processes (threads), communication is provided by sending asynchronous messages
Seif Haridi and Peter Van Roy 98
Components in different languages
• An intermediate common language is defined to allow components to communicate given that the language provide the same computation model
• A common example is CORBA IDL (Interface Definition Language) which maps a language entity to a common format at the client component, and does the inverse mapping at the service-provider component
• The components are normally reside on different operating system processes (or even on different machines)
• This approach works if the components are relatively large and the interaction is relatively infrequent
Seif Haridi and Peter Van Roy 99
Illustration (one way)
A component C1calling the function (method) f(x) in theComponent C2
Translate f(x) fromlanguage L1 (structured data) to IDL (sequence of bytes)
Translate f(x) fromlanguage IDL (sequence of bytes) tolanguage L2 (structured data)
A component C2 invoking the function (method) f(x)
top related