SlideShare ist ein Scribd-Unternehmen logo
1 von 83
Downloaden Sie, um offline zu lesen
Continuations &
Web Applications
        -Balaji Damodaran, ThoughtWorks
Contiuation

●
    Continuation is Time Travel


●
    Continuation is saving the control flow of
    a program's execution
class ControlCentre

      def exploreTerrain
          marsPlateau = Plateau.new(5, 5)
          alpha = Rover.new("alpha")
          source = Position.new(1, 2, "N")
          alpha.land(marsPlateau, source)
          destination = alpha.explore("LMLMLMLMM")
          print destination
      end
end
class ControlCentre

      def exploreTerrain
          marsPlateau = Plateau.new(5, 5)
          alpha = Rover.new("alpha")
          source = Position.new(1, 2, "N")
          alpha.land(marsPlateau, source)
          destination = alpha.explore("LMLMLMLMM")
          print destination
      end
end
class ControlCentre

      def exploreTerrain
          marsPlateau = Plateau.new(5, 5)
          alpha = Rover.new("alpha")
          source = Position.new(1, 2, "N")
          alpha.land(marsPlateau, source)
          destination = alpha.explore("LMLMLMLMM")
          print destination
      end
end




  Control Scope
  Execution Context
  marsPlateau
  alpha
class ControlCentre

      def exploreTerrain
          marsPlateau = Plateau.new(5, 5)
          alpha = Rover.new("alpha")
          source = Position.new(1, 2, "N")
          alpha.land(marsPlateau, source)
          destination = alpha.explore("LMLMLMLMM")
          print destination
      end
end




  Control Scope                          Current Continuation
  Execution Context        source = Position.new(1, 2, "N")
  marsPlateau              alpha.land(marsPlateau, source)
                           destination = alpha.explore("LMLMLMLMM")
  alpha                    print destination
class ControlCentre

      def exploreTerrain
          marsPlateau = Plateau.new(5, 5)
          alpha = Rover.new("alpha")
          callcc{|@cc|}
          source = Position.new(1, 2, "N")
          alpha.land(marsPlateau, source)
          destination = alpha.explore("LMLMLMLMM")
          print destination
          return @cc
      end
end
class ControlCentre

      def exploreTerrain
          marsPlateau = Plateau.new(5, 5)
          alpha = Rover.new("alpha")
          callcc{|@cc|}
          source = Position.new(1, 2, "N")
          alpha.land(marsPlateau, source)
          destination = alpha.explore("LMLMLMLMM")
          print destination
          return @cc
      end
end

> c = exploreTerrain
“1 3 N”
=> #<Continuation:0xb744a8c4>

> c.call
“1 3 N”
=> #<Continuation:0xb744a8c4>
Normal      Control Flow with
                                    Continuation invoked
Control Flow     Continuations




                           continuation           continuation
Isn't that just a glorified GOTO?
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>
Normal      Control Flow with Continuation invoked
Control Flow     Continuations with different parameters




                                                continuation
                           continuation         With different
                                                parameters
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.."
Normal        Control Flow with Continuation reinvoked
Control Flow   Continuations paused   with parameters




                                             continuation
                                             With parameters

                             continuation
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.
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
Normal      Control Flow marked with
Control Flow         continuation

                                                         Memory



                                      Local variables
                                                           #




                                          continuation
A new process that
        invokes a continuation

                                               Memory



                                                 #




          The current execution is abandoned




Note: Global data does not
get stored in a continuation
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.
Continuations Sandwich Analogy
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”
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
call-with-current-continuation
Method definition:
function: call/cc(function: f) {
   c = new: Continuation
   f(c)
}

JavaScript (Rhino):
function callcc(f) {
   var c = new Continuation();
   return f(c);
}

Ruby:
callcc {|cont|} cont => Continuation object
cont.call(*args)
call-with-current-continuation
function callcc(fun) {
  var continuation = new Continuation()
  return fun(continuation)
}

var cc
print(3 * (8 + callcc(function(c) {
                 cc = c
                 return 4
               })))

js> 36
call-with-current-continuation
function callcc(fun) {
  var continuation = new Continuation()
  return fun(continuation)
}

var cc
print(3 * (8 + callcc(function(c) {
                 cc = c
                 return 4
               })))

js> 36

js> cc(6)
42
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
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
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
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.
The following code is strictly for session purposes
only. Implementing this in usable code may cause
               harm to life and limb.
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
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
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
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
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
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)
Continuations Types


●
    First class continuations
●
    Continuation Passing Style (CPS)
●
    Delimited Continuations
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
Continuation Passing Style



function (arg) {    function (arg, k) {
   //computation       //computation
   return result;      k(result);
}                   }
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
CPS - Example
function add_cps(x, y, c) {
   c(x + y)
}

function square_cps(x, c) {
   c(x * x)
}
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)
                                    })
                  })
}
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
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.
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
Normal         Control Flow with
Control Flow   Delimited Continuations        Continuation invoked




                               Continuation -
                               start

                                                           Delimited
                                                           continuation



                             Continuation -
                             end
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.
Delimited Continuations
reset {
   shift { k: (Int=>Int) =>
      k(7)
   } + 1
} * 2


scala>
16




CPS transformed
2 * (1 + 7)
Delimited Continuations
reset {
   shift { k: (Int=>Int) =>
      k(7)
   } + 1
} * 2


scala>
16
__________________________________________________________

reset {            def foo() {
   foo() + 1          shift { k: (Int=>Int) =>
} * 2                    k(7)
                      }
                   }

CPS transformed
2 * (1 + 7)
Delimited Continuations
reset{
   1 + shift{ k: (Int=>Int) =>
         k(k(7))
      }
} * 3

scala>
27


reset{
   1 + shift{ k: (Int=>Int) =>
         k(k(7))
      } * 3
}

scala>
67
Delimited Continuations
reset{
   1 + shift{ k: (Int=>Int) =>
         k(k(7))
      }
} * 3

scala>
27        CPS Transform:   (1 + (1 + 7)) * 3 = 27


reset{
   1 + shift{ k: (Int=>Int) =>
         k(k(7))
      } * 3
}

scala>
67        CPS Transform:   (1 + (1 + 7 * 3) * 3) = 67
So... ummm..
Whats the real world use of this thing?
Applications of Continuations
●
    Pause and Play e.g. User Interface design
●
    Backtracking
●
    Coroutines
●
    Exception Handling
●
    Web Frameworks
●
    Compiler & Interpreter implementation
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
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
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
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
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
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
Web Servers with Continuations
           support
●   Continuity (Perl)
●   Jetty 6 (Java)
●   Plt-Scheme web server (Scheme)
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
Seaside - Installation
     One – click install experience
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'
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
Image from - Seaside – A Multiple Control Flow Web Application Framework, Stéphane Ducasse
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
SimpleCounter>>initialize
  super initialize.
  counter := 0.

SimpleCounter>>renderContentOn: html
  html heading: 'the counter is ', counter asString.
  html anchor
     callback: [ counter := counter + 1 ];
     with: 'increase'.
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.
Image from - Seaside – A Multiple Control Flow Web Application Framework, Stéphane Ducasse
Problem with full continuation


        Response 1          Response 2




      Continuation saved   Continuation invoked




     Request 1               Request 2
Solved with delimited
    continuation
 Response 1

                      Response 2
 Delimited
 Continuation saved


                       Delimited
                       Continuation invoked




 Request 1            Request 2
Challenges
●
    Understanding continuations as a concept
●
    Debugging
●
    Buying into the 'heretic' idea
Seaside – Demo
References
●   http://en.wikipedia.org/wiki/Continuation
●   http://idea-log.blogspot.com/2005/10/why-are-continuations-so-confusing-
    and.html
●   http://www.iam.unibe.ch/~scg/Archive/Papers/Duca04eSeaside.pdf
●   http://vimeo.com/13304075
●   http://www.intertwingly.net/blog/2005/04/13/Continuations-for-Curmudgeons
●   http://www.cs.indiana.edu/~dfried/appcont.pdf
●   http://lambda-the-ultimate.org/node/86
●   http://en.wikipedia.org/wiki/Continuation-passing_style
●   http://lamp.epfl.ch/~rompf/continuations-icfp09.pdf
●   http://book.seaside.st/book
●   http://en.wikipedia.org/wiki/Call-with-current-continuation
●   http://www.ibm.com/developerworks/java/library/j-contin.html
●   http://www.cs.brown.edu/~sk/Publications/Papers/Published/khmgpf-impl-use-
    plt-web-server-journal/
●   http://double.co.nz/pdf/continuations.pdf

Weitere ähnliche Inhalte

Was ist angesagt?

Csphtp1 05
Csphtp1 05Csphtp1 05
Csphtp1 05HUST
 
Being functional in PHP
Being functional in PHPBeing functional in PHP
Being functional in PHPDavid de Boer
 
Csphtp1 13
Csphtp1 13Csphtp1 13
Csphtp1 13HUST
 
O CPAN tem as ferramentas que você precisa para fazer TDD em Perl, o Coding D...
O CPAN tem as ferramentas que você precisa para fazer TDD em Perl, o Coding D...O CPAN tem as ferramentas que você precisa para fazer TDD em Perl, o Coding D...
O CPAN tem as ferramentas que você precisa para fazer TDD em Perl, o Coding D...Rodolfo Carvalho
 
Nesting of for loops using C++
Nesting of for loops using C++Nesting of for loops using C++
Nesting of for loops using C++prashant_sainii
 
.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund
.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund
.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel ZikmundKarel Zikmund
 
clap: Command line argument parser for Pharo
clap: Command line argument parser for Pharoclap: Command line argument parser for Pharo
clap: Command line argument parser for PharoESUG
 
The Ring programming language version 1.5 book - Part 4 of 31
The Ring programming language version 1.5 book - Part 4 of 31The Ring programming language version 1.5 book - Part 4 of 31
The Ring programming language version 1.5 book - Part 4 of 31Mahmoud Samir Fayed
 
Recursion to iteration automation.
Recursion to iteration automation.Recursion to iteration automation.
Recursion to iteration automation.Russell Childs
 
Lecture#6 functions in c++
Lecture#6 functions in c++Lecture#6 functions in c++
Lecture#6 functions in c++NUST Stuff
 
The Ring programming language version 1.5.3 book - Part 89 of 184
The Ring programming language version 1.5.3 book - Part 89 of 184The Ring programming language version 1.5.3 book - Part 89 of 184
The Ring programming language version 1.5.3 book - Part 89 of 184Mahmoud Samir Fayed
 
systems programming lab programs in c
systems programming lab programs in csystems programming lab programs in c
systems programming lab programs in cMeghna Roy
 
The Ring programming language version 1.5.2 book - Part 20 of 181
The Ring programming language version 1.5.2 book - Part 20 of 181The Ring programming language version 1.5.2 book - Part 20 of 181
The Ring programming language version 1.5.2 book - Part 20 of 181Mahmoud Samir Fayed
 
The Ring programming language version 1.5.1 book - Part 74 of 180
The Ring programming language version 1.5.1 book - Part 74 of 180The Ring programming language version 1.5.1 book - Part 74 of 180
The Ring programming language version 1.5.1 book - Part 74 of 180Mahmoud Samir Fayed
 

Was ist angesagt? (20)

Csphtp1 05
Csphtp1 05Csphtp1 05
Csphtp1 05
 
C++loop statements
C++loop statementsC++loop statements
C++loop statements
 
Being functional in PHP
Being functional in PHPBeing functional in PHP
Being functional in PHP
 
Csphtp1 13
Csphtp1 13Csphtp1 13
Csphtp1 13
 
verilog code
verilog codeverilog code
verilog code
 
O CPAN tem as ferramentas que você precisa para fazer TDD em Perl, o Coding D...
O CPAN tem as ferramentas que você precisa para fazer TDD em Perl, o Coding D...O CPAN tem as ferramentas que você precisa para fazer TDD em Perl, o Coding D...
O CPAN tem as ferramentas que você precisa para fazer TDD em Perl, o Coding D...
 
Nesting of for loops using C++
Nesting of for loops using C++Nesting of for loops using C++
Nesting of for loops using C++
 
.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund
.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund
.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund
 
clap: Command line argument parser for Pharo
clap: Command line argument parser for Pharoclap: Command line argument parser for Pharo
clap: Command line argument parser for Pharo
 
Nested loops
Nested loopsNested loops
Nested loops
 
Stack prgs
Stack prgsStack prgs
Stack prgs
 
The Ring programming language version 1.5 book - Part 4 of 31
The Ring programming language version 1.5 book - Part 4 of 31The Ring programming language version 1.5 book - Part 4 of 31
The Ring programming language version 1.5 book - Part 4 of 31
 
C - ISRO
C - ISROC - ISRO
C - ISRO
 
Recursion to iteration automation.
Recursion to iteration automation.Recursion to iteration automation.
Recursion to iteration automation.
 
4th unit full
4th unit full4th unit full
4th unit full
 
Lecture#6 functions in c++
Lecture#6 functions in c++Lecture#6 functions in c++
Lecture#6 functions in c++
 
The Ring programming language version 1.5.3 book - Part 89 of 184
The Ring programming language version 1.5.3 book - Part 89 of 184The Ring programming language version 1.5.3 book - Part 89 of 184
The Ring programming language version 1.5.3 book - Part 89 of 184
 
systems programming lab programs in c
systems programming lab programs in csystems programming lab programs in c
systems programming lab programs in c
 
The Ring programming language version 1.5.2 book - Part 20 of 181
The Ring programming language version 1.5.2 book - Part 20 of 181The Ring programming language version 1.5.2 book - Part 20 of 181
The Ring programming language version 1.5.2 book - Part 20 of 181
 
The Ring programming language version 1.5.1 book - Part 74 of 180
The Ring programming language version 1.5.1 book - Part 74 of 180The Ring programming language version 1.5.1 book - Part 74 of 180
The Ring programming language version 1.5.1 book - Part 74 of 180
 

Ähnlich wie Continuations

Asynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsAsynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsPiotr Pelczar
 
The Ring programming language version 1.8 book - Part 88 of 202
The Ring programming language version 1.8 book - Part 88 of 202The Ring programming language version 1.8 book - Part 88 of 202
The Ring programming language version 1.8 book - Part 88 of 202Mahmoud Samir Fayed
 
Tail Recursion in data structure
Tail Recursion in data structureTail Recursion in data structure
Tail Recursion in data structureRumman Ansari
 
SystemVerilog Assertion.pptx
SystemVerilog Assertion.pptxSystemVerilog Assertion.pptx
SystemVerilog Assertion.pptxNothing!
 
Job Queue in Golang
Job Queue in GolangJob Queue in Golang
Job Queue in GolangBo-Yi Wu
 
Async Debugging - A Practical Guide to survive !
Async Debugging - A Practical Guide to survive !Async Debugging - A Practical Guide to survive !
Async Debugging - A Practical Guide to survive !Mirco Vanini
 
Functional programming with Ruby - can make you look smart
Functional programming with Ruby - can make you look smartFunctional programming with Ruby - can make you look smart
Functional programming with Ruby - can make you look smartChen Fisher
 
The Ring programming language version 1.3 book - Part 59 of 88
The Ring programming language version 1.3 book - Part 59 of 88The Ring programming language version 1.3 book - Part 59 of 88
The Ring programming language version 1.3 book - Part 59 of 88Mahmoud Samir Fayed
 
Promises - Asynchronous Control Flow
Promises - Asynchronous Control FlowPromises - Asynchronous Control Flow
Promises - Asynchronous Control FlowHenrique Barcelos
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSAdam L Barrett
 
Control Structures in C
Control Structures in CControl Structures in C
Control Structures in Csana shaikh
 
Control Statement.ppt
Control Statement.pptControl Statement.ppt
Control Statement.pptsanjay
 
Openstack taskflow 簡介
Openstack taskflow 簡介Openstack taskflow 簡介
Openstack taskflow 簡介kao kuo-tung
 

Ähnlich wie Continuations (20)

Asynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsAsynchronous programming done right - Node.js
Asynchronous programming done right - Node.js
 
The Ring programming language version 1.8 book - Part 88 of 202
The Ring programming language version 1.8 book - Part 88 of 202The Ring programming language version 1.8 book - Part 88 of 202
The Ring programming language version 1.8 book - Part 88 of 202
 
人力
人力人力
人力
 
Tail recursion
Tail recursionTail recursion
Tail recursion
 
Tail Recursion in data structure
Tail Recursion in data structureTail Recursion in data structure
Tail Recursion in data structure
 
Ch7
Ch7Ch7
Ch7
 
SystemVerilog Assertion.pptx
SystemVerilog Assertion.pptxSystemVerilog Assertion.pptx
SystemVerilog Assertion.pptx
 
Introduction to c part -1
Introduction to c   part -1Introduction to c   part -1
Introduction to c part -1
 
Job Queue in Golang
Job Queue in GolangJob Queue in Golang
Job Queue in Golang
 
Async Debugging - A Practical Guide to survive !
Async Debugging - A Practical Guide to survive !Async Debugging - A Practical Guide to survive !
Async Debugging - A Practical Guide to survive !
 
Functional programming with Ruby - can make you look smart
Functional programming with Ruby - can make you look smartFunctional programming with Ruby - can make you look smart
Functional programming with Ruby - can make you look smart
 
The Ring programming language version 1.3 book - Part 59 of 88
The Ring programming language version 1.3 book - Part 59 of 88The Ring programming language version 1.3 book - Part 59 of 88
The Ring programming language version 1.3 book - Part 59 of 88
 
Promises - Asynchronous Control Flow
Promises - Asynchronous Control FlowPromises - Asynchronous Control Flow
Promises - Asynchronous Control Flow
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJS
 
Control Structures in C
Control Structures in CControl Structures in C
Control Structures in C
 
PLSQL
PLSQLPLSQL
PLSQL
 
Control Statement.ppt
Control Statement.pptControl Statement.ppt
Control Statement.ppt
 
Openstack taskflow 簡介
Openstack taskflow 簡介Openstack taskflow 簡介
Openstack taskflow 簡介
 
7 functions
7  functions7  functions
7 functions
 
Looping
LoopingLooping
Looping
 

Continuations

  • 1. Continuations & Web Applications -Balaji Damodaran, ThoughtWorks
  • 2.
  • 3.
  • 4. Contiuation ● Continuation is Time Travel ● Continuation is saving the control flow of a program's execution
  • 5.
  • 6. class ControlCentre def exploreTerrain marsPlateau = Plateau.new(5, 5) alpha = Rover.new("alpha") source = Position.new(1, 2, "N") alpha.land(marsPlateau, source) destination = alpha.explore("LMLMLMLMM") print destination end end
  • 7. class ControlCentre def exploreTerrain marsPlateau = Plateau.new(5, 5) alpha = Rover.new("alpha") source = Position.new(1, 2, "N") alpha.land(marsPlateau, source) destination = alpha.explore("LMLMLMLMM") print destination end end
  • 8. class ControlCentre def exploreTerrain marsPlateau = Plateau.new(5, 5) alpha = Rover.new("alpha") source = Position.new(1, 2, "N") alpha.land(marsPlateau, source) destination = alpha.explore("LMLMLMLMM") print destination end end Control Scope Execution Context marsPlateau alpha
  • 9. class ControlCentre def exploreTerrain marsPlateau = Plateau.new(5, 5) alpha = Rover.new("alpha") source = Position.new(1, 2, "N") alpha.land(marsPlateau, source) destination = alpha.explore("LMLMLMLMM") print destination end end Control Scope Current Continuation Execution Context source = Position.new(1, 2, "N") marsPlateau alpha.land(marsPlateau, source) destination = alpha.explore("LMLMLMLMM") alpha print destination
  • 10. class ControlCentre def exploreTerrain marsPlateau = Plateau.new(5, 5) alpha = Rover.new("alpha") callcc{|@cc|} source = Position.new(1, 2, "N") alpha.land(marsPlateau, source) destination = alpha.explore("LMLMLMLMM") print destination return @cc end end
  • 11. class ControlCentre def exploreTerrain marsPlateau = Plateau.new(5, 5) alpha = Rover.new("alpha") callcc{|@cc|} source = Position.new(1, 2, "N") alpha.land(marsPlateau, source) destination = alpha.explore("LMLMLMLMM") print destination return @cc end end > c = exploreTerrain “1 3 N” => #<Continuation:0xb744a8c4> > c.call “1 3 N” => #<Continuation:0xb744a8c4>
  • 12. Normal Control Flow with Continuation invoked Control Flow Continuations continuation continuation
  • 13. Isn't that just a glorified GOTO?
  • 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.
  • 25.
  • 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
  • 28. call-with-current-continuation Method definition: function: call/cc(function: f) { c = new: Continuation f(c) } JavaScript (Rhino): function callcc(f) { var c = new Continuation(); return f(c); } Ruby: callcc {|cont|} cont => Continuation object cont.call(*args)
  • 29. call-with-current-continuation function callcc(fun) { var continuation = new Continuation() return fun(continuation) } var cc print(3 * (8 + callcc(function(c) { cc = c return 4 }))) js> 36
  • 30. call-with-current-continuation function callcc(fun) { var continuation = new Continuation() return fun(continuation) } var cc print(3 * (8 + callcc(function(c) { cc = c return 4 }))) js> 36 js> cc(6) 42
  • 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
  • 45. Continuation Passing Style function (arg) { function (arg, k) { //computation //computation return result; k(result); } }
  • 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.
  • 55. Delimited Continuations reset { shift { k: (Int=>Int) => k(7) } + 1 } * 2 scala> 16 CPS transformed 2 * (1 + 7)
  • 56. Delimited Continuations reset { shift { k: (Int=>Int) => k(7) } + 1 } * 2 scala> 16 __________________________________________________________ reset { def foo() { foo() + 1 shift { k: (Int=>Int) => } * 2 k(7) } } CPS transformed 2 * (1 + 7)
  • 57. Delimited Continuations reset{ 1 + shift{ k: (Int=>Int) => k(k(7)) } } * 3 scala> 27 reset{ 1 + shift{ k: (Int=>Int) => k(k(7)) } * 3 } scala> 67
  • 58. Delimited Continuations reset{ 1 + shift{ k: (Int=>Int) => k(k(7)) } } * 3 scala> 27 CPS Transform: (1 + (1 + 7)) * 3 = 27 reset{ 1 + shift{ k: (Int=>Int) => k(k(7)) } * 3 } scala> 67 CPS Transform: (1 + (1 + 7 * 3) * 3) = 67
  • 59. So... ummm.. Whats the real world use of this thing?
  • 60.
  • 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
  • 71. Seaside - Installation One – click install experience
  • 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
  • 80. Solved with delimited continuation Response 1 Response 2 Delimited Continuation saved Delimited Continuation invoked Request 1 Request 2
  • 81. Challenges ● Understanding continuations as a concept ● Debugging ● Buying into the 'heretic' idea
  • 83. References ● http://en.wikipedia.org/wiki/Continuation ● http://idea-log.blogspot.com/2005/10/why-are-continuations-so-confusing- and.html ● http://www.iam.unibe.ch/~scg/Archive/Papers/Duca04eSeaside.pdf ● http://vimeo.com/13304075 ● http://www.intertwingly.net/blog/2005/04/13/Continuations-for-Curmudgeons ● http://www.cs.indiana.edu/~dfried/appcont.pdf ● http://lambda-the-ultimate.org/node/86 ● http://en.wikipedia.org/wiki/Continuation-passing_style ● http://lamp.epfl.ch/~rompf/continuations-icfp09.pdf ● http://book.seaside.st/book ● http://en.wikipedia.org/wiki/Call-with-current-continuation ● http://www.ibm.com/developerworks/java/library/j-contin.html ● http://www.cs.brown.edu/~sk/Publications/Papers/Published/khmgpf-impl-use- plt-web-server-journal/ ● http://double.co.nz/pdf/continuations.pdf