programming)languages)) and)techniques) (cis120))cis120/archive/15fa/lectures/lec17.pdf · valid...
TRANSCRIPT
![Page 1: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/1.jpg)
Programming Languages and Techniques
(CIS120)
Lecture 17 October 12th , 2015
More Queue ManipulaEon
“Objects”
![Page 2: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/2.jpg)
Announcements • Homework 4: Queues
– Due: Tomorrow, October 13th at 11:59 pm
• Homework 5: GUI Library & Paint – Available Soon – Due: Thursday, October 22nd
![Page 3: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/3.jpg)
CIS120
What happens when you run this funcEon on a (valid) queue containing 2 elements?
1. The value 2 is returned2. The value 0 is returned 3. StackOverflow4. Your program hangs
let f (q:'a queue) : int = let rec loop (qn:'a qnode option) : int = begin match qn with | None -> 0 | Some n -> 1 + loop qn end in loop q.head
![Page 4: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/4.jpg)
CIS120
What happens when you run this funcEon on a (valid) queue containing 2 elements?
1. The value 2 is returned2. The value 0 is returned 3. StackOverflow4. Your program hangs
let f (q:'a queue) : int = let rec loop (qn:'a qnode option) (len:int) : int = begin match qn with | None -> len | Some n -> loop qn (len + 1) end in loop q.head 0
![Page 5: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/5.jpg)
More queue iteraEon examples
to_list print
get_tail
![Page 6: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/6.jpg)
to_list (using iteraEon)
• Here, the state maintained across each iteraEon of the loop is the queue “index pointer” no and the (reversed) list of elements traversed.
• The “exit case” post processes the list by reversing it.
6
(* Retrieve the list of values stored in the queue, ordered from head to tail. *)let to_list (q: 'a queue) : 'a list = let rec loop (no: 'a qnode option) (l:'a list) : 'a list = begin match no with | None -> List.rev l | Some n -> loop n.next (n.v::l) end in loop q.head []
![Page 7: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/7.jpg)
print (using iteraEon)
• Here, the only state needed is the queue “index pointer”.
7
let print (q:'a queue) (string_of_element:'a -> string) : unit = let rec loop (no: 'a qnode option) : unit = begin match no with | None -> () | Some n -> print_endline (string_of_element n.v); loop n.next end in print_endline "--- queue contents ---"; loop q.head; print_endline "--- end of queue -----"
![Page 8: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/8.jpg)
Singly-‐linked Queue Processing • General structure (schemaEcally) :
• What is useful to put in the state? – Accumulated informaEon about the queue (e.g. length so far) – Link to previous node (so that it could be updated, for example)
(* Process a singly-linked queue. *)let queue_operation (q: 'a queue) : ’b = let rec loop (current: 'a qnode option) (s:'a state) : ‘b = begin match no with | None -> … (* iteration complete, produce result *)
| Some n -> … (* do something with n, create new loop state *) loop current.next new_s
end in loop q.head init
![Page 9: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/9.jpg)
valid
9
(* Determine whether the q satisfies the q invariant *)let valid (q: 'a queue) : bool = begin match (q.head,q.tail) with | (None,None) -> true | (Some n1,Some n2) -> begin match get_tail n1 with | Some n -> n2 == n (* tail is the last node *) | None -> false end | (_,_) -> false end
Either: (1) head and tail are both None (i.e. the queue is empty) or (2) head is Some n1, tail is Some n2 and -‐ n2 is reachable from n1 by following ‘next’ pointers -‐ n2.next is None
![Page 10: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/10.jpg)
get_tail (using iteraEon)
• This funcEon works even if the queue has cycles. – It returns Some qn if qn is a “tail” reachable from hd (qn may be hd) – It returns None if there is a cycle
• The state is an index pointer and a list of all the nodes seen. – contains_alias is a helper funcEon that checks to see whether n has an
alias in the list
10
(* get the tail (if any) from a queue *)let rec get_tail (hd: 'a qnode) : 'a qnode option = let rec loop (qn: 'a qnode) (seen: 'a qnode list) : 'a qnode option = begin match qn.next with | None -> Some qn | Some n -> if contains_alias n seen then None else loop n (qn::seen) end in loop hd []
![Page 11: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/11.jpg)
General Guidelines • Processing must maintain the queue invariants • Update the head and tail references (if necessary) • If changing the link structure:
– SomeEmes useful to keep reference to the previous node (allows removal of the current node)
• Drawing pictures of the queue heap structure is helpful
• If iteraEng over the whole queue (e.g. to find an element) – It is usually not useful to use helpers like “is_empty” or “contains”
because you will have to account for those cases during the traversal anyway!
![Page 12: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/12.jpg)
“Objects” and Hidden State
EncapsulaEng State
![Page 13: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/13.jpg)
CIS120
What number is printed by this program?
1. 12. 23. 34. 45. 56. other
let f = let x = 2 in fun (y : int) -> x + ylet x = 4;; print_int (f 1)
How did you answer this quesEon? 1. SubsEtuEon model 2. Abstract Stack Machine 3. I just knew the answer 4. I didn’t know, so I guessed
Answer: 3
![Page 14: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/14.jpg)
An “incr” funcEon • FuncEons with internal state
• Drawbacks: – No abstrac0on: There is only one counter in the world. If we want
another, we need another counter_state value and another incr funcEon.
– No encapsula0on: Any other code can modify count, too.
16
type counter_state = { mutable count:int }
let ctr = { count = 0 }
(* each call to incr will produce the next integer *)let incr () : int = ctr.count <- ctr.count + 1; ctr.count
![Page 15: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/15.jpg)
Using Hidden State • Make a funcEon that creates a counter state and an incr
funcEon each Eme a counter is needed.
17
(* More useful: a counter generator: *)let mk_incr () : unit -> int = (* this ctr is private to the returned function *) let ctr = { count = 0 } in fun () -> ctr.count <- ctr.count + 1; ctr.count
(* make one counter *) let incr1 : unit -> int = mk_incr ()
(* make another counter *)let incr2 : unit -> int = mk_incr ()
![Page 16: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/16.jpg)
CIS120
What number is printed by this program?
1. 12. 23. 34. other
Answer: 1
let mk_incr () : unit -> int = let ctr = { count = 0 } in fun () -> ctr.count <- ctr.count + 1; ctr.count
let incr1 = mk_incr () (* make one counter *) let incr2 = mk_incr () (* and another *)
let _ = incr1 () in print_int (incr2 ())
![Page 17: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/17.jpg)
Running mk_incr
let mk_incr () : unit -> int = let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
let incr1 : unit -> int = mk_incr ()
Workspace Stack Heap
19
![Page 18: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/18.jpg)
Running mk_incr
let mk_incr : unit -> unit -> int = fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
let incr1 : unit -> int = mk_incr ()
Workspace Stack Heap
20
![Page 19: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/19.jpg)
Running mk_incr
let mk_incr : unit -> unit -> int = fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
let incr1 : unit -> int = mk_incr ()
Workspace Stack Heap
21
![Page 20: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/20.jpg)
Running mk_incr
let mk_incr : unit -> unit -> int = let incr1 : unit -> int = mk_incr ()
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
22
![Page 21: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/21.jpg)
Running mk_incr
let mk_incr : unit -> unit -> int = . let incr1 : unit -> int = mk_incr ()
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
23
![Page 22: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/22.jpg)
Running mk_incr
let incr1 : unit -> int = mk_incr ()
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
24
![Page 23: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/23.jpg)
Running mk_incr
let incr1 : unit -> int = mk_incr ()
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
25
![Page 24: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/24.jpg)
Running mk_incr
let incr1 : unit -> int = ( ())
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
26
![Page 25: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/25.jpg)
Running mk_incr
let incr1 : unit -> int = ( ())
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
27
![Page 26: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/26.jpg)
Running mk_incr
let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
let incr1 : unit -> int = ( )
28
![Page 27: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/27.jpg)
Running mk_incr
let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
let incr1 : unit -> int = ( )
29
![Page 28: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/28.jpg)
Running mk_incr
let ctr = in fun () -> ctr.count <- ctr.count + 1; ctr.count
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
let incr1 : unit -> int = ( )
count 0
30
![Page 29: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/29.jpg)
Running mk_incr
let ctr = in fun () -> ctr.count <- ctr.count + 1; ctr.count
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
let incr1 : unit -> int = ( )
count 0
31
![Page 30: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/30.jpg)
Running mk_incr
fun () -> ctr.count <- ctr.count + 1; ctr.count
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
let incr1 : unit -> int = ( )
count 0ctr
32
![Page 31: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/31.jpg)
Running mk_incr
fun () -> ctr.count <- ctr.count + 1; ctr.count
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
let incr1 : unit -> int = ( )
count 0ctr
33
![Page 32: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/32.jpg)
Local FuncEons Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
let incr1 : unit -> int = ( )
count 0ctr
fun () -> ctr.count <- ctr.count + 1; ctr.count
NOTE: We need one refinement of the ASM model to handle local funcEons. Why? The funcEon menEons “ctr”, which is on the stack (but about to be popped off)…
…so we save a copy of the needed stack bindings with the funcEon itself. (This is someEmes called a closure…)
ctr
34
![Page 33: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/33.jpg)
Local FuncEons Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
let incr1 : unit -> int = ( )
count 0ctr
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
POP!
35
![Page 34: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/34.jpg)
Local FuncEons Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 0
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
let incr1 : unit -> int = ( )
36
![Page 35: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/35.jpg)
Local FuncEons Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 0
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
let incr1 : unit -> int = ( )
37
![Page 36: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/36.jpg)
Local FuncEons Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 0
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
incr1
DONE! Note how the count record is accessible only via the incr1 funcEon. This is the sense in which the state is “local” to incr1.
38
![Page 37: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/37.jpg)
Now let’s run “incr1 ()” Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 0
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
incr1 () incr1
39
![Page 38: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/38.jpg)
Now let’s run “incr1 ()” Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 0
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
incr1 () incr1
40
![Page 39: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/39.jpg)
Now let’s run “incr1 ()” Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 0
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
( ()) incr1
41
![Page 40: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/40.jpg)
Now let’s run “incr1 ()” Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 0
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
( ()) incr1
42
![Page 41: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/41.jpg)
Now let’s run “incr1 ()”
ctr.count <- ctr.count + 1;ctr.count
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 0
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
( )
incr1
ctr
NOTE: Since the funcEon had some saved stack bindings, we add them to the stack at the same Eme that we put the code in the workspace.
43
![Page 42: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/42.jpg)
Now let’s run “incr1 ()”
ctr.count <- ctr.count + 1;ctr.count
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 0
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
( )
incr1
ctr
44
![Page 43: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/43.jpg)
Now let’s run “incr1 ()”
.count <- ctr.count + 1;ctr.count
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 0
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
( )
incr1
ctr
45
![Page 44: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/44.jpg)
Now let’s run “incr1 ()”
.count <- ctr.count + 1;ctr.count
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 0
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
( )
incr1
ctr
46
![Page 45: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/45.jpg)
Now let’s run “incr1 ()”
.count <- .count + 1;ctr.count
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 0
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
( )
incr1
ctr
47
![Page 46: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/46.jpg)
Now let’s run “incr1 ()”
.count <- .count + 1;ctr.count
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 0
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
( )
incr1
ctr
48
![Page 47: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/47.jpg)
Now let’s run “incr1 ()”
.count <- 0 + 1;ctr.count
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 0
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
( )
incr1
ctr
49
![Page 48: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/48.jpg)
Now let’s run “incr1 ()”
.count <- 0 + 1;ctr.count
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 0
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
( )
incr1
ctr
50
![Page 49: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/49.jpg)
Now let’s run “incr1 ()”
.count <- 1;ctr.count
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 0
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
( )
incr1
ctr
51
![Page 50: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/50.jpg)
Now let’s run “incr1 ()”
.count <- 1;ctr.count
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 0
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
( )
incr1
ctr
52
![Page 51: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/51.jpg)
Now let’s run “incr1 ()”
();ctr.count
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 1
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
( )
incr1
ctr
53
![Page 52: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/52.jpg)
Now let’s run “incr1 ()”
();ctr.count
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 1
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
( )
incr1
ctr
54
![Page 53: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/53.jpg)
Now let’s run “incr1 ()”
ctr.count
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 1
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
( )
incr1
ctr
55
![Page 54: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/54.jpg)
Now let’s run “incr1 ()”
ctr.count
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 1
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
( )
incr1
ctr
56
![Page 55: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/55.jpg)
Now let’s run “incr1 ()”
.count
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 1
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
( )
incr1
ctr
57
![Page 56: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/56.jpg)
Now let’s run “incr1 ()”
.count
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 1
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
( )
incr1
ctr
58
![Page 57: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/57.jpg)
Now let’s run “incr1 ()”
1
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 1
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
( )
incr1
ctr
59
![Page 58: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/58.jpg)
Now let’s run “incr1 ()”
1
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 1
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
( )
incr1
ctr
POP!
60
![Page 59: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/59.jpg)
Now let’s run “incr1 ()”
1
Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 1
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
incr1
DONE!
61
![Page 60: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/60.jpg)
Now Let’s run mk_incr again Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 1
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
let incr2 : unit -> int = mk_incr () incr1
62
![Page 61: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/61.jpg)
…Eme passes…
![Page 62: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/62.jpg)
Ajer creaEng incr2 Workspace Stack Heap
fun () -> let ctr = {count = 0} in fun () -> ctr.count <- ctr.count + 1; ctr.count
mk_incr
count 1
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
incr1
count 0
fun () -> ctr.count <- ctr.count + 1; ctr.count
ctr
incr2
NOTE: the two different incr funcEons have separate local states because a new count record was created in each call to mk_incr.
64
![Page 63: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/63.jpg)
One step further • mk_incr shows us how to create different instance of local
state so that we can have several different counters. • What if we want to bundle together several operaEons that
share the same local state? – e.g. incr and decr operaEons that work on the same counter
65
![Page 64: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/64.jpg)
A Counter Object
66
(* The type of counter objects *)type counter = { get : unit -> int; incr : unit -> unit; decr : unit -> unit; reset : unit -> unit;}
(* Create a fresh counter object with hidden state: *)let new_counter () : counter = let ctr = {count = 0} in { get = (fun () -> ctr.count) ; incr = (fun () -> ctr.count <- ctr.count + 1) ; decr = (fun () -> ctr.count <- ctr.count - 1) ; reset = (fun () -> ctr.count <- 0) ; }
![Page 65: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/65.jpg)
let c1 = mk_counter ()Stack Heap
fun () -> let ctr = {count = 0} in { … }
new_counter
count 1 fun () -> ctr.count
ctr
67
fun () -> ctr.count <- ctr.count + 1
ctr
fun () -> ctr.count <- ctr.count – 1
ctr
fun () -> ctr.count <- 0
ctr
get
incr
decr
reset
c1
![Page 66: Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15fa/lectures/lec17.pdf · valid ))) 9 (* Determine whether the q satisfies the q invariant *) let valid (q: 'a queue)](https://reader034.vdocument.in/reader034/viewer/2022050418/5f8ddf8623742a42a305fe09/html5/thumbnails/66.jpg)
Using Counter Objects
68
(* a helper function to create a nice string for printing *)let ctr_string (s:string) (i:int) = s ^ ".ctr = " ^ (string_of_int i) ^ "\n" let c1 = new_counter ()let c2 = new_counter ()
;; print_string (ctr_string "c1" (c1.get ()));; c1.incr ();; c1.incr ();; print_string (ctr_string "c1" (c1.get ()));; c1.decr ();; print_string (ctr_string "c1" (c1.get ()));; c2.incr ();; print_string (ctr_string "c2" (c2.get ()));; c2.decr ();; print_string (ctr_string "c2" (c2.get ()))