17

How are people using continuations on a larger and smaller scale in Scala?

Are any parts of the Scala standard library written in CPS?

Are there any major performance penalties in using continuations?

Mohamed Bana
  • 1,251
  • 2
  • 17
  • 27
  • 5
    one nit: CPS (continuation-passing style) is something that is possible in any language that has or can simulate higher order functions. For example, when you pass a callback object to a method in Java, that's actually an example of CPS. Scala's *delimited continuations* plugin provides a way to write control structures which look syntactically like "direct style" but which are transformed into CPS behind the scenes. – Tom Crockett Oct 27 '10 at 07:51

2 Answers2

14

I'm using this to turn asynchronous functions of the form def func(...)(followup: Result => Unit): Unit so that instead of writing

foo(args){result1 => 
  bar(result1){result2 => 
     car(result2) {result3 =>
       //etc.
     }
  }
}

you can write

val result1 = foo(args)
val result2 = bar(result1)
val result3 = car(result2)

or

car(bar(foo(args)))

(note: the functions are not limited to one argument or just the use of previous results as arguments)

See http://www.tikalk.com/java/blog/asynchronous-functions-actors-and-cps

IttayD
  • 28,271
  • 28
  • 124
  • 178
7

Scala-ARM (Automatic-Resource-Management) uses delimited continuations

import java.io._
import util.continuations._
import resource._
def each_line_from(r : BufferedReader) : String @suspendable =
  shift { k =>
    var line = r.readLine
    while(line != null) {
      k(line)
      line = r.readLine
    }
  }
reset {
  val server = managed(new ServerSocket(8007)) !
  while(true) {
    // This reset is not needed, however the  below denotes a "flow" of execution that can be deferred.
    // One can envision an asynchronous execuction model that would support the exact same semantics as below.
    reset {
      val connection = managed(server.accept) !
      val output = managed(connection.getOutputStream) !
      val input = managed(connection.getInputStream) !
      val writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(output)))
      val reader = new BufferedReader(new InputStreamReader(input))
      writer.println(each_line_from(reader))
      writer.flush()
    }
  }
}
oluies
  • 17,694
  • 14
  • 74
  • 117
  • 1
    Excuse me, but what are the benefits of writing it like this?

    So the continuation is `k`, which represents a println followed by a flush statement? I'm not seeing the benefits of using CPS in this case.
    – Mohamed Bana Oct 29 '10 at 11:57