14. class ControlCentre
def exploreTerrain
marsPlateau = Plateau.new(5, 5)
alpha = Rover.new("alpha")
c = nil
source = callcc do |cc|
c = cc
Position.new(1, 2, "N")
end
alpha.land(marsPlateau, source)
destination = alpha.explore("LMLMLMLMM")
print destination
return c
end
end
> c = exploreTerrain
“1 3 N”
=> #<Continuation:0xb7466240>
> c.call(Position.new(2, 3, “E”))
“2 4 E”
=> #<Continuation:0xb7466240>
15. Normal Control Flow with Continuation invoked
Control Flow Continuations with different parameters
continuation
continuation With different
parameters
16. def continuation
puts "i do some computation " +
"& save the state of execution."
m = callcc { |cc| return cc }
puts "then i restart the execution from " +
"the saved state & pass custom " +
"values such as "#{m[0]}" and "#{m[1]}""
end
> c = continuation
i do some computation & save the state of execution.
> c.call("so..", "then..")
then i restart the execution from the saved state & pass custom
values such as "so.." and "then.."
17. Normal Control Flow with Continuation reinvoked
Control Flow Continuations paused with parameters
continuation
With parameters
continuation
18.
19. Continuation?
●
A continuation reifies the control flow of a
program as just another data value
●
Reify – To consider an abstract concept to be
real. To make control flow as first class
functions/objects.
20. Continuation
●
Continuation is an object that takes a
snapshot copy of the running process.
●
The current process is copied and saved.
●
Current process – execution context and
all local variables
21. Normal Control Flow marked with
Control Flow continuation
Memory
Local variables
#
continuation
22. A new process that
invokes a continuation
Memory
#
The current execution is abandoned
Note: Global data does not
get stored in a continuation
23. Continuations
●
A Continuation stores the execution context, its
references and pointers.
●
However, it does not store the heap data or
data that is outside the scope of local
references and pointers.
●
So any change made to them will stay changed
even after invoking the continuation.
26. call-with-current-continuation
●
call-with-current-continuation, in short
called as “call/cc” is a procedure first
introduced in Scheme.
●
Now exists in several other programming
languages such as Ruby, known as
“callcc”
27. call-with-current-continuation
● call/cc takes in only one argument, which is a
function f.
● It takes the current continuation as an object and
applies f to it.
– continuation = new Continuation()
– function(continuation)
●
When, callcc gets invoked, the program flow will
continue from the point it was captured and the
argument to the continuation will become its
return value
31. def continue_example
i = 0
print "Before callcc #{i}n"
callcc do |cc|
for i in 1..10 do
print "In callcc #{i}n"
return cc if i > 5
end
end
print "After callcc #{i}n"
end
32. def continue_example
i = 0
print "Before callcc #{i}n"
callcc do |cc|
for i in 1..10 do
print "In callcc #{i}n"
return cc if i > 5
end
end
print "After callcc #{i}n"
end
puts "begin control flow."
c = continue_example()
puts "after invoking the method"
if c
c.call
puts "this will not get executed"
end
33. def continue_example
i = 0
print "Before callcc #{i}n"
callcc do |cc| begin control flow.
for i in 1..10 do Before callcc 0
print "In callcc #{i}n" In callcc 1
return cc if i > 5 In callcc 2
end In callcc 3
end In callcc 4
print "After callcc #{i}n" In callcc 5
end In callcc 6
after invoking the method
After callcc 6
after invoking the method
puts "begin control flow."
c = continue_example()
puts "after invoking the method"
if c
c.call
puts "this will not get executed"
end
34. call-with-current-continuation
●
Continuations are sort of goto labels. But
more powerful.
●
We can store the continuation in a variable or
object field, unlike a goto label.
●
Goto labels are restricted within a functional
scope, continuations are not limited by that.
35. The following code is strictly for session purposes
only. Implementing this in usable code may cause
harm to life and limb.
36. Continuation as a GOTO
def goto_in_ruby_1
i = 0
callcc {|@label|}
i = i + 1
print "#{i}t"
@label.call if i < 10
end
37. Continuation as a GOTO
def goto_in_ruby_1
i = 0
callcc {|@label|}
i = i + 1
print "#{i}t"
@label.call if i < 10
end
output:
1 2 3 4 5 6 7 8 9 10
38. Continuation as a GOTO
def goto_in_ruby_1 def goto_in_ruby_2
i = 0 i = 0
callcc {|@label|} callcc do |label|
i = i + 1 label.call
print "#{i}t" i = 99
@label.call if i < 10 end
end print i
end
output:
1 2 3 4 5 6 7 8 9 10
39. Continuation as a GOTO
def goto_in_ruby_1 def goto_in_ruby_2
i = 0 i = 0
callcc {|@label|} callcc do |label|
i = i + 1 label.call
print "#{i}t" i = 99
@label.call if i < 10 end
end print i
end
output: output:
1 2 3 4 5 6 7 8 9 10 0
40. Summary
●
Continuation is a procedure that represents
the remaining steps in a computation.
●
It is a "snapshot" of the current control
context or control state of the program
●
The continuation can be later invoked
(repeatedly) with custom arguments
41. Continuations
●
Languages that support first class
continuations
●
Scheme (call/cc)
●
Ruby (callcc)
●
Smalltalk (Continuation currentDo:)
●
Rhino [JavaScript] (new Continuation())
●
Scala (Responder & shift, reset)
●
Perl (Coro)
●
Haskell (Control.Monad.Cont)
42. Continuations Types
●
First class continuations
●
Continuation Passing Style (CPS)
●
Delimited Continuations
43.
44. Continuation Passing Style
●
A function, instead of returning an explict
value, it takes an explict 'continuation'
argument – another function which is
meant to receive the result of the
computation
46. CPS - Example
function add(x, y) {
return x + y
}
function square(x) {
return x * x
}
function calculate(x, y) {
return add(square(x), square(y))
}
js> print(calculate(3, 4))
=> 25
47. CPS - Example
function add_cps(x, y, c) {
c(x + y)
}
function square_cps(x, c) {
c(x * x)
}
48. CPS - Example
function add_cps(x, y, c) {
c(x + y)
}
function square_cps(x, c) {
c(x * x)
}
function calculate_cps(x, y, c) {
square_cps(x, function(v) {
square_cps(y, function(r){
add_cps(v,r,c)
})
})
}
49. CPS - Example
function add_cps(x, y, c) {
c(x + y)
}
function square_cps(x, c) {
c(x * x)
}
function calculate_cps(x, y, c) {
square_cps(x, function(v) {
square_cps(y, function(r){
add_cps(v,r,c)
})
})
}
js> calculate_cps(3, 4, print)
=> 25
js> calculate_cps(3, 4, function(v) {print(sqrt(v))});
=> 5
50. CPS
● CPS is used in programming languages that do not
have first – class continuations, but have first –
class functions
● Every call is a tail call and if used without Tail Call
Optimization (TCO), the continuation would grow
during recursion
● Using CPS and TCO, compilers and interperters of
some programming languages managed to
eliminate the need for a runtime stack.
51.
52. Delimited Continuations
● Delimited (or partial, or composable) continuations are
more like regular functions and less like GOTOs. They
do not embody the entire rest of the computation, but
just a partial rest, up to a programmer-defined outer
bound.
● delimited continuations will return control to the caller
after they are invoked, and they may also return values
– Tiark Rompf, Ingo Maier, Martin Odersky
53. Normal Control Flow with
Control Flow Delimited Continuations Continuation invoked
Continuation -
start
Delimited
continuation
Continuation -
end
54. Delimited Continuations
●
Delimited Continuations are manipulated
by means of two primitives, shift and
reset.
●
Calling shift captures the current
continuation, and reset defines the
boundary up to which the continuation
reaches.
61. Applications of Continuations
●
Pause and Play e.g. User Interface design
●
Backtracking
●
Coroutines
●
Exception Handling
●
Web Frameworks
●
Compiler & Interpreter implementation
62. Problems
●
Page centric
●
HTTP Stateless-ness causes heavy use of
session, cookies
●
'Back' button in user interaction pages
●
Browser cloning in user interaction pages
●
Inversion of control
63. def add_two_numbers
n1 = callcc { |cc| return ask("1st number:", cc) }
n2 = callcc { |cc| return ask("2nd number:", cc) }
print "sum of two numbers is #{n1 + n2}n"
end
64. def add_two_numbers
n1 = callcc { |cc| return ask("1st number:", cc) }
n2 = callcc { |cc| return ask("2nd number:", cc) }
print "sum of two numbers is #{n1 + n2}n"
end
irb> add_two_numbers
1st number:
respond with: submit(25, ...): => #<Continuation:0xb76e0e58>
irb> submit(25, 30)
2nd number:
respond with: submit(37, ...): => #<Continuation:0xb76ddde8>
irb> submit(37, 12)
sum of two numbers is 42
=> nil
65. def add_two_numbers
n1 = callcc { |cc| return ask("1st number:", cc) }
n2 = callcc { |cc| return ask("2nd number:", cc) }
print "sum of two numbers is #{n1 + n2}n"
end
@session = Hash.new
def ask(str, cc)
r = rand(100).to_i
print "#{str}nrespond with: submit(#{r}, ...): "
@session[r] = cc
cc
end
def submit(id, number)
@session[id].call(number)
End
66. Continuations lookup table (session)
Server renders the
page and saves the The continuation
continuation in the object is looked up
session with a uuid based on the uuid The page is
1 4 in the url and rendered with the
executed uuid given in the
url
server
2
call: page a
call: page b client
call: page c
3
Client makes a
server response
with required
information
67. Web Frameworks
●
Seaside in Smalltalk (v 3.1)
●
Wee in Ruby (v 2.1)
●
Nagare in Python (v 0.3)
●
Apache Cocoon in Java (v 2.2)
●
RIFE in Java (v 1.6)
●
Ocsigen in OCaml (v 1.3)
●
Weblocks in Common Lisp
68. Web Servers with Continuations
support
● Continuity (Perl)
● Jetty 6 (Java)
● Plt-Scheme web server (Scheme)
69.
70. Seaside
● Written in Smalltalk
● Often called the 'heretic' framework because it doesn't
follow the 'conventional' web wisdom
– Clean urls
– Templates to separate model and view
– Share as little state as possible
– Urls contain session identifiers
– There is no 'view' or html templates. Views are part of smalltalk objects
– Seaside continuations & callbacks give a stateful behavior
72. Seaside - Workspace
●
Smalltalk deals with image snapshots for
saving the workspace.
●
There is no concept of 'files' and 'editors'
●
Class objects are created through 'object
browser' and code is executed through a
'workspace'
73. Seaside - Components
● Components represent the whole of a page or portion of
pages
● The inherit from 'WAComponent' class
● Components maintain state
● Component's response loop
– Renders the component
– Waits for user's input
– Executes a block of code when a link or button is pressed
– Re-renders itself or another component in place
74. Image from - Seaside – A Multiple Control Flow Web Application Framework, Stéphane Ducasse
75. Seaside - callbacks
● Every user interaction on the web page triggers a
callback.
●
A callback can be on a link, button or any other
form elements
●
The callback will execute a block of code whose
result will end in re-rendering the component or
a new component
76. SimpleCounter>>initialize
super initialize.
counter := 0.
SimpleCounter>>renderContentOn: html
html heading: 'the counter is ', counter asString.
html anchor
callback: [ counter := counter + 1 ];
with: 'increase'.
77. Seaside - Continuations
● Call / Answer
● call: takes a component as a parameter and it swaps
the current component for the new component
● The new component will be rendered and user action
will cause a callback to run that'll send an answer:
● The value passed to answer: will be returned to call:
and the program will continue from there.
78. Image from - Seaside – A Multiple Control Flow Web Application Framework, Stéphane Ducasse
79. Problem with full continuation
Response 1 Response 2
Continuation saved Continuation invoked
Request 1 Request 2