C# async implemented in scala (based on delimited continuations)

174 views
Skip to first unread message

Daniel

unread,
Feb 15, 2012, 7:28:47 PM2/15/12
to scala-user
Hi all

In order to get a better understanding about delimited continuations I
tried to implement something akin to C# async [1]. Since I think this
has the potential to be cool, I share it with you. I would appreciate
any hints and comments.

As a substitute for C#s Tasks I went with akka 2.0 Futures [2] since
those will eventually be integrated into the main library [3] afaik.
I have the following:


== Example ==

context(GUI) { implicit ec =>
async {
m("1")

val contentCom = await { dlWebSite("http://www.google.com") }
m("2 " + contentCom)

val contentCh = await { dlWebSite("http://www.google.ch") }
m("3 " + contentCh)

val contentDe = await { dlWebSite("http://www.google.de") }
m("4 " + contentDe)
}
}

// Returns a Future which will eventually hold the downloaded html.
// The download itself is scheduled on a thread pool.
def dlWebSite(url: String): Future[String] = Future {
m("downloading: " + url)
Source.fromURL(new URL(url))
(Codec.ISO8859).getLines.mkString.take(20)
}(ThreadPool)

// Prints msg prefixed with the name of the current thread
def m(msg: String) = println(Thread.currentThread().getName() + " '" +
msg + "'")


== Output ==

UI '1'
pool-1-thread-1 'downloading: http://www.google.com'
UI '2 <!doctype html><html'
pool-1-thread-3 'downloading: http://www.google.ch'
UI '3 <!doctype html><html'
pool-1-thread-5 'downloading: http://www.google.de'
UI '4 <!doctype html><html'

As you can see, the hard work is executed on a thread pool but the
results are again on the UI thread. No blocking behind the scenes.


== Implementation ==

// The async method is nothing more than a nice name for
// scala.util.continuations.reset
def async[B](block: => Unit@suspendable): Unit = reset[Unit,Unit]
{ block }

// The await method takes a block which returns a Future[A] and
// pretends to return an A to the caller. Without continuations, this
would be
// only possible by waiting (blocking) on the future until the result
is ready.
def await[A](block: => Future[A])(implicit ec: ExecutionContext =
ThreadPool): A@suspendable = shift { cont: (A => Unit) =>
block onSuccess { case r => ec.execute{ cont(r) } }
}

// The context method is used to put an ExecutionContext into scope
// which runs the given block. It primarily exists to give nice
// looking examples.
def context[T](ec: ExecutionContext)(block: ExecutionContext => T)
{ ec.execute{ block(ec) } }

// Dummy placeholder to simulate the Swing event dispatching thread
val GUI =
ExecutionContexts.fromExecutor(Executors.newSingleThreadExecutor(
new ThreadFactory{ def newThread(r: Runnable): Thread = new
Thread(r,"UI")}))

// Thread pool for the heavy background work
val ThreadPool = ExecutionContexts.fromExecutorService(

Executors.newFixedThreadPool(10))

// Runnables without the noise
implicit def toRunnable[T](f: => T ): Runnable = new Runnable { def
run() = f }


== The Problem ==

I would like the async block to return a Future of its syntactic
return value:

val a: Future[Int] = async[Int] {
m("1")
val com = await[String,Int,NotLast] {
dlWebSite("http://www.google.com")
}
m("2 " + com)

val ch = await[String,Int,NotLast] {
dlWebSite("http://www.google.ch")
}
m("3 " + ch)

val de = await[String,Int,Last] {
dlWebSite("http://www.google.de")
}
m("4 " + de)

de.length() // this should be returned as a Future[Int]
}
a onSuccess { case r => m("res" + r) }


== Output ==

UI '1'
pool-1-thread-1 'downloading: http://www.google.com'
UI '2 <!doctype html><html'
pool-1-thread-3 'downloading: http://www.google.ch'
UI '3 <!doctype html><html'
pool-1-thread-5 'downloading: http://www.google.de'
UI '4 <!doctype html><html'
UI 'res20'

The good part is that it works. The problem is, that now all
those hairy type declarations are required. I could life with
await[String,Int] {...} but my solution requires a further type
parameter to distinguish whether it is the last await in a reset
block or not. The last await turns the Int into a Future[Int]
and all awaits above that last one need to reflect this in their
type. Here is the code:

// Better name for reset. Takes a block with a syntactic return type
// of B and returns a Future[B]
def async[B](block: => B@cpsParam[B,Future[B]]): Future[B] =
reset[B,Future[B]] { block }

// The D[_] type parameter is required in @cpsParam.
// Depending on the given type the matching implicit is searched.
def await[A,B,D[_]] (block: => Future[A])
(implicit ec: ExecutionContext = ThreadPool,
f: (=> Future[A]) => ExecutionContext => A@cpsParam[D[B],Future[B]]
):A@cpsParam[D[B],Future[B]] = f(block)(ec)


type Last[X] = X

// The last await needs a continuation form A => Last[B] which is from
A => B
implicit def last[A,B]: (=> Future[A]) => ExecutionContext =>
A@cpsParam[Last[B],Future[B]] = {
block => ec => shift[A,Last[B],Future[B]] { cont: (A => Last[B]) =>
val p = Promise[B]()(ec)
block onSuccess { case a => ec.execute{ p.success(cont(a)) } }
p
}
}

type NotLast[X] = Future[X]

// All other awaits need a continuation from A => NotLast[B]
// which is from A => Future[B]
implicit def notLast[A,B]: (=> Future[A]) => ExecutionContext =>
A@cpsParam[NotLast[B],Future[B]] = {
block => ec => shift[A,NotLast[B],Future[B]] { cont: (A =>
NotLast[B]) =>
val p = Promise[B]()(ec)
block onSuccess { case a =>
ec.execute{ p.completeWith(cont(a)) } }
p
}
}

This was the best solution I was able to come up with. Of course I
could offer two different await methods which would be a simple
solution if they had different names. But that is not an option. BTW I
am fully aware that the presented code has at most toy quality (
handles only onSuccess, etc.). Anyway, thanks for reading that far. If
you want to learn about scala's continuations I recommend reading this
blog post [4] by Jim McBeath.

Thanks Daniel


[1] http://msdn.microsoft.com/en-us/vstudio/gg316360
[2] http://akka.io/docs/akka/2.0-RC1/scala/futures.html
[3] http://docs.scala-lang.org/sips/pending/futures-promises.html
[4] http://jim-mcbeath.blogspot.com/2010/08/delimited-continuations.html

Tiark Rompf

unread,
Feb 16, 2012, 6:40:01 AM2/16/12
to Daniel, scala-user
Sweet! Would this version of async

def async[A](body: => A @suspendable) = {
val p = promise[A]
reset { p success body }
p
}

work for the extended case you mention?

val a: Future[Int] = async[Int] {

val com = await { dlWebSite("http://www.google.com") }
com.length
}

a onSuccess { case r => .... }


- Tiark

√iktor Ҡlang

unread,
Feb 16, 2012, 6:48:39 AM2/16/12
to Tiark Rompf, Daniel, scala-user
I think we already got this covered with the dataflow API in Akka:

http://akka.io/docs/akka/2.0-RC1/scala/dataflow.html

Cheers,

--
Viktor Klang

Akka Tech Lead
Typesafe - The software stack for applications that scale

Twitter: @viktorklang

Tiark Rompf

unread,
Feb 16, 2012, 7:18:09 AM2/16/12
to √iktor Ҡlang, Daniel, scala-user
Yes, the differences are minor:

def flow[A](body: => A @cps[Future[Any]]): Future[A]

def async[A](body: => A @suspendable): Future[A]

this one avoids the Future[Any] part.

- Tiark

√iktor Ҡlang

unread,
Feb 16, 2012, 7:24:24 AM2/16/12
to Tiark Rompf, Daniel, scala-user
2012/2/16 Tiark Rompf <tiark...@epfl.ch>:

> Yes, the differences are minor:
>
>        def flow[A](body: => A @cps[Future[Any]]): Future[A]
>
>        def async[A](body: => A @suspendable): Future[A]
>
> this one avoids the Future[Any] part.

What are the pros/cons?

Daniel

unread,
Feb 16, 2012, 9:12:45 AM2/16/12
to scala-user
Hi Tiark

> Sweet! Would this version of async
>
> def async[A](body: => A @suspendable) = {
>         val p = promise[A]
>         reset { p success body }
>         p
> }
>
> work for the extended case you mention?

Yes it does. I really should have asked earlier =) Many thanks for
this simple solution!

def async[A](body: => A @suspendable): Future[A] = {
val p = Promise[A]()
reset { p success body; () } // The '()' is required for
successful type inference
p
}

def await[A](block: => Future[A])(implicit ec: ExecutionContext):
A@suspendable = shift { cont: (A => Unit) =>
block onSuccess { case r => ec.execute{ cont(r) } }
}

Cheers Daniel

///////////////////////////////// full
example ////////////////////////////

import scala.util.continuations._
import akka.dispatch._
import java.util.concurrent.Executors
import java.net.URL
import java.util.concurrent.ThreadFactory

object TiarkExample extends App {
implicit def toRunnable[T](f: => T): Runnable = new Runnable { def
run() = f }
implicit val GUI =
ExecutionContexts.fromExecutor(Executors.newSingleThreadExecutor(new
ThreadFactory{ def newThread(r: Runnable): Thread = new
Thread(r,"UI")}))
val POOL =
ExecutionContexts.fromExecutor(Executors.newFixedThreadPool(2))

def async[A](body: => A @suspendable): Future[A] = {
val p = Promise[A]()
reset { p success body; () }
p
}

def await[A](block: => Future[A])(implicit ec: ExecutionContext):
A@suspendable = shift { cont: (A => Unit) =>
block onSuccess { case r => ec.execute{ cont(r) } }
}

val a = async {
m("1")
val com = await { downloadWebSiteTask("http://www.google.com")}
m("2")
val ch = await { downloadWebSiteTask("http://www.google.ch")}
m("3")
ch.length + com.length
}

a onSuccess { case r => m("result: " + r)}

def downloadWebSiteTask(url: String): Future[String] = Future {
m("downloading: " + url)
io.Source.fromURL(new URL(url))
(io.Codec.ISO8859).getLines.mkString.take(20)
}(POOL)

Daniel

unread,
Feb 16, 2012, 9:34:05 AM2/16/12
to scala-user
Hi Victor

> I think we already got this covered with the dataflow API in Akka:

Right! I just tried it:

  val a = flow {
    m("1")
    val com = downloadWebSiteTask("http://www.google.com")()
    m("2")
    val ch = downloadWebSiteTask("http://www.google.ch")()
    m("3")
    ch.length + com.length
  }
  a onSuccess { case r => m("result: " + r)}

Output:

UI '1'
pool-1-thread-1 'downloading: http://www.google.com'
pool-1-thread-2 '2'   HERE
pool-1-thread-1 'downloading: http://www.google.ch'
pool-1-thread-1 '3'   HERE
pool-1-thread-1 'result: 40'  HERE

What would I have to do if I need the 'callbacks' to be executed on
the implicit ExecutionContext (the one that flow{..}(ctx) captures)?

Daniel

√iktor Ҡlang

unread,
Feb 16, 2012, 9:42:04 AM2/16/12
to Daniel, scala-user

That's a good one! Let me see what we can do about that.

Cheers,

>
> Daniel

Daniel Kröni

unread,
Feb 16, 2012, 9:57:36 AM2/16/12
to √iktor Ҡlang, scala-user
Hi Victor

This is maybe also worth a discussion:

def namedCtx(n: String) = ExecutionContexts.fromExecutor(
Executors.newSingleThreadExecutor( new ThreadFactory {
def newThread(r: Runnable) = new Thread(r,n)
}))

val A = namedCtx("A")
val B = namedCtx("B")

// create a promise with ctx A
val p = Promise[String]()(A)

// I would expect that any callback from p
// is executed in the context of p
p onSuccess{
case r => println(Thread.currentThread().getName() + " " + r)
}

p.completeWith(Future{"Hi"}(B))

The above prints "B Hi"

What do you think?

√iktor Ҡlang

unread,
Feb 16, 2012, 10:06:43 AM2/16/12
to Daniel Kröni, scala-user
Hi Daniel,

2012/2/16 Daniel Kröni <daniel...@gmail.com>:

final def completeWith(other: Future[T]): this.type = {
    other onComplete { tryComplete(_) }
    this
  }

Cheers,

Derek Williams

unread,
Feb 16, 2012, 10:38:33 AM2/16/12
to √iktor Ҡlang, Tiark Rompf, Daniel, scala-user
2012/2/16 √iktor Ҡlang <viktor...@gmail.com>

2012/2/16 Tiark Rompf <tiark...@epfl.ch>:
> Yes, the differences are minor:
>
>        def flow[A](body: => A @cps[Future[Any]]): Future[A]
>
>        def async[A](body: => A @suspendable): Future[A]
>
> this one avoids the Future[Any] part.

What are the pros/cons?


They handle exceptions differently. 'flow' propagates the exception through the futures, and it looks like 'async' ignores it (although some cases could probably be implemented).

I originally did 'flow' with @suspendable, but there was a situation where I just couldn't get the exception to continue through, causing the final future to timeout. I think it had something to do with having the type inferred as a Future[Nothing] (back in the olden days).

--
Derek Williams

Daniel

unread,
Feb 16, 2012, 5:15:43 PM2/16/12
to scala-user
Hi Derek, All

> They handle exceptions differently. 'flow' propagates the exception through
> the futures, and it looks like 'async' ignores it (although some cases
> could probably be implemented).

I implement some exception handling [1] and polished the example [2].
Any comments?

Thanks Daniel

[1] https://github.com/danielkroeni/scala-async/blob/master/src/main/scala/async/Async.scala
[2] https://github.com/danielkroeni/scala-async/blob/master/src/main/scala/async/Example.scala



Eric Kolotyluk

unread,
Feb 17, 2012, 6:23:28 PM2/17/12
to scala...@googlegroups.com
I have been trying to follow this discussion, as it really fascinates me, and while I get the gist of it, I cannot grok it.

I still struggle with continuations in Scala
  1. I have never been able to get them to work in the Eclipse/Scala environment. It would be nice if they could 'just work' - but they don't. Consequently I cannot even play with them.
  2. I have not internalized the concepts the way one would internalize say recursion or closures.
I have an interest in continuations particularly in the context of being able to write UI code that can only run on a single thread, but has to interact with background tasks and asynchronous activities.

I would appreciate it if someone could take the time explain what is going on in this particular discussion as I do find it fascinating.

Cheers, Eric

Vlad Patryshev

unread,
Feb 18, 2012, 3:39:18 AM2/18/12
to Eric Kolotyluk, scala...@googlegroups.com
Hmm, did you develop in JS? Closures everywhere.

Thanks,
-Vlad

Dave

unread,
Feb 18, 2012, 10:04:59 AM2/18/12
to scala-user
Have you in Eclipse entered continuations:enable in the P textbox?
You can find it in Preferences > Scala > Compiler on the Standard tab

Maybe you have to clean you project too (if you have a false
NoSuchMethod error bugging you).

That is all there is. (No Xplugin path to continuations.jar necessary
on the Advanced tab, someone suggested that in scala-ide bugreport,
but I don't have it and it works too)

Create a scala project

This code works with scala-ide

Main.scala
==========
import scala.util.continuations._

object Main extends App {

def is123(n:Int):Boolean = {
reset {
shift { k : (Int=>String) =>
(k(n) == "123")
}.toString
}
}

println("the result is " +
reset {
shift { k: (Int=>Int) =>
k(k(k(7)))
} + 1
})

println("123 == 123? result is " + is123(123))
println("567 == 123? result is " + is123(567))
}


Output:
======

the result is 10
123 == 123? result is true
567 == 123? result is false





On 18 feb, 00:23, Eric Kolotyluk <eric.koloty...@gmail.com> wrote:
> I have been trying to follow this discussion, as it really fascinates
> me, and while I get the gist of it, I cannot grok it.
>
> I still struggle with continuations in Scala
>
>  1. I have never been able to get them to work in the Eclipse/Scala
>     environment. It would be nice if they could 'just work' - but they
>     don't. Consequently I cannot even play with them.
>  2. I have not internalized the concepts the way one would internalize

Dave

unread,
Feb 18, 2012, 10:16:17 AM2/18/12
to scala-user
Interesting link about Swarm + Scala Delimited Continuations:

http://code.google.com/p/swarm-dpl/

Eric Kolotyluk

unread,
Feb 18, 2012, 11:49:53 PM2/18/12
to Vlad Patryshev, scala...@googlegroups.com
What is JS?

Cheers, Eric

Constantine Plotnikov

unread,
Feb 19, 2012, 9:56:00 AM2/19/12
to Eric Kolotyluk, scala...@googlegroups.com
You might consider using AsyncScala library for the task. Then annonce on LtU was:  http://lambda-the-ultimate.org/node/4289 

It has explicit support for E-style actor-based programming over GUI event loop and much more (like RX-like event streams). There even samples related to it. Out-of-the box AWT event loop is supported. But adding support for SWT, should be very easy.

Thanks,
Constantine

Daniel

unread,
Feb 19, 2012, 10:17:31 AM2/19/12
to scala-user, eric.ko...@gmail.com
Hi Eric

I really recommend reading the blog post by Jim McBeath [1]. I will
not be able to give a better explanation. But I will try to explain
how delimited continuations can be used to simplify asynchronous
programming.

Consider the following code fragment:

reset {
  VAL A: A = shift { cont: (A => B) =>
    // do something with cont.
  }
  VAL B: B = ...
  B
}
println("after reset")

The code will be transformed in a way, that everything between shift
and the end of reset (all in UPPERcase) will be passed as the function
'cont' to shift. In other words: The uppercase part becomes the
function cont. Compare how the type of cont (A => B) aligns exactly
with the uppercase part.

After the transformation you have a situation similar to the following
where 'cont' is the upper-case part.

{ cont: (A => B) =>
  // do something with cont.
}
println("after reset")

If you don't call the cont function, the uppercase part will not be
executed at all and control flow goes on with the part which was
originally after the reset block. If you call the cont function, it
will execute the uppercase part.


Let's see how we can use this for asynchronous programming:

reset {
  val s: String = reset {  cont: (String => Unit) =>
     new Thread() {
       def run {
          val news = downloadNews("www.cnn.com")
          cont(news) // call the cont with the result
       }
     }.start
  }
  println("news: " + s)
}
println("after reset")

In the above fragment, the call to reset returns after the new
background thread has been created and started. It will immediately
print "after reset". In the meantime the background thread loaded the
news from a webservice. Now it will call 'cont' with the downloaded
news. The val s will get assigned to the news argument passed to cont
and "news: ..." will be printed.


Instead of calling cont(news) in the background thread, one can use
for example SwingHelper to execute the 'cont' on the Swing EDT.

reset {
  val s: String = reset {  cont: (String => Unit) =>
     new Thread() {
       def run {
          val news = downloadNews("www.cnn.com")
          SwingUtilities.invokeLater(new Runnable { def run
{ cont(news)} })
       }
     }.start
  }
  println("news: " + s)
}

In the above code, the continuation 'cont' will be called on the Swing
thread. This means that println("news: " + s) will be executed on the
swing thread. You could directly assign the s to a Swing Textbox or
similar.

Not sure if this helps.

Cheers
Daniel

[1] http://jim-mcbeath.blogspot.com/2010/08/delimited-continuations.html

On Feb 18, 12:23 am, Eric Kolotyluk <eric.koloty...@gmail.com> wrote:
> I have been trying to follow this discussion, as it really fascinates
> me, and while I get the gist of it, I cannot grok it.
>
> I still struggle with continuations in Scala
>
>  1. I have never been able to get them to work in the Eclipse/Scala
>     environment. It would be nice if they could 'just work' - but they
>     don't. Consequently I cannot even play with them.
>  2. I have not internalized the concepts the way one would internalize

Eric Kolotyluk

unread,
Feb 19, 2012, 11:03:38 AM2/19/12
to scala...@googlegroups.com
The Eclipse IDE shows

bad option: -P:continuations:enable

Dave

unread,
Feb 19, 2012, 11:06:02 AM2/19/12
to scala-user
> That is all there is. (No Xplugin path to continuations.jar necessary
> on the Advanced tab, someone suggested that in scala-ide bugreport,
> but I don't have it and it works too)

After retesting today it seems that the reference to continuations.jar
is necessary
So on Advanced tab Textbox Xplugin enter the path to continuations.jar
e.g.
C:\scala-2.9.1.final\misc\scala-devel\plugins\continuations.jar

Dave

unread,
Feb 19, 2012, 11:24:31 AM2/19/12
to scala-user
Hi Daniel, the second reset should be a shift and run should have an
override keyword>

I add it to the previous example:

import scala.util.continuations._

object Main extends App {

def is123(n:Int):Boolean = {
reset {
shift { k : (Int=>String) =>
(k(n) == "123")
}.toString
}
}

def downloadNews(s: String) = { Thread.sleep(5000); "cnn news
headlines" }

reset {
val s: String = shift { cont: (String => Unit) =>
new Thread() {
override def run {
val news = downloadNews("www.cnn.com")
cont(news)
}
}.start
}
println("news: " + s)
}
println("after reset")


println("the result is " +
reset {
shift { k: (Int=>Int) =>
k(k(k(7)))
} + 1
})

println("123 == 123? result is " + is123(123))
println("567 == 123? result is " + is123(567))
}


Output:
after reset
the result is 10
123 == 123? result is true
567 == 123? result is false
news: cnn news headlines

and the last line shows up after 5 seconds
> > Cheers, Eric- Tekst uit oorspronkelijk bericht niet weergeven -
>
> - Tekst uit oorspronkelijk bericht weergeven -

Dave

unread,
Feb 19, 2012, 11:28:07 AM2/19/12
to scala-user
You shouldn't use -P:
only

continuations:enable

Dave

unread,
Feb 20, 2012, 7:26:47 AM2/20/12
to scala-user
Maybe you have Use Project Properties enabled

Then you can fill them in on project level in Project > Properties >
Scala Compiler

and clean project before running

On 19 feb, 17:03, Eric Kolotyluk <eric.koloty...@gmail.com> wrote:

Eric Kolotyluk

unread,
Feb 20, 2012, 10:29:45 AM2/20/12
to scala...@googlegroups.com
I did not have "Use Project Settings" enabled previously.

I tried enabling "Use Project Settings" and setting
"continuations:enable" in the P field, but that just produces "bad
option: -P:continuations:enable" as well.

This has been my ongoing problem with continuations in Scala - it is
simply too difficult to configure it to work in Eclipse - consequently I
cannot even experiment with the feature.

Should I create a JIRA issue on this?

Cheers, Eric

Daniel Sobral

unread,
Feb 20, 2012, 11:12:29 AM2/20/12
to Eric Kolotyluk, scala...@googlegroups.com
On Mon, Feb 20, 2012 at 13:29, Eric Kolotyluk <eric.ko...@gmail.com> wrote:
> I did not have "Use Project Settings" enabled previously.
>
> I tried enabling "Use Project Settings" and setting "continuations:enable"
> in the P field, but that just produces "bad option: -P:continuations:enable"
> as well.

It sounds like you are using Scala 2.8.x... are you?

--
Daniel C. Sobral

I travel to the future all the time.

Eric Kolotyluk

unread,
Feb 20, 2012, 11:47:36 AM2/20/12
to Daniel Sobral, scala...@googlegroups.com
As far as I can tell I am using Scala 2.9.0.1 - at least that is all I
have installed - unless Scala on Eclipse is using some embedded Scala.

Cheers, Eric

Dave

unread,
Feb 20, 2012, 1:23:47 PM2/20/12
to scala-user
And you have set textbox Xplugin on the Advanced tab the path to
continuations.jar
e.g.
C:\scala-2.9.1.final\misc\scala-devel\plugins\continuations.jar


Probably for you it is
C:\scala-2.9.0.1\misc\scala-devel\plugins\continuations.jar
otherwise you can search

You can see what version of Scala your project is using see Scala
Library and then between the square brackets is the version
> >>>> - Tekst uit oorspronkelijk bericht weergeven -- Tekst uit oorspronkelijk bericht niet weergeven -

Eric Kolotyluk

unread,
Feb 20, 2012, 5:19:34 PM2/20/12
to scala...@googlegroups.com
Wha-Hoo - got it to compile and run. Thanks so much :-)

Kinda sucks that the path in the Xplugin cannot have any spaces in the
name. I had to move the plug-in somewhere else. My Scala is installed in

C:\Program Files (Open)\Scala\scala-2.9.0.1

I guess continuations are still consider experimental which is why there
is so much fuss around setting them up in Eclipse.

Cheers, Eric

Mirco Dotta

unread,
Feb 21, 2012, 8:38:50 AM2/21/12
to Eric Kolotyluk, scala...@googlegroups.com
Hi Eric, all,

Enabling the continuations plugin in the Scala IDE for Eclipse is actually very simple, and to help
with that I just wrote a short tutorial:

http://scala-ide.org/docs/tutorials/continuations-plugin/index.html

There is no need to explicitly pass -Xplugin, that because the continuations.jar is shipped together
with the Scala distribution and by default -Xpluginsdir points to the directory containing the
continuations.jar.

If you have any comment, please feel free to drop me an email.

Cheers,
Mirco

Dave

unread,
Feb 21, 2012, 8:44:48 AM2/21/12
to scala-user
Hi Mirco,
in practice the reference to continuations.jar is still necessary.
Maybe it is a bug

Dave

unread,
Feb 21, 2012, 9:03:57 AM2/21/12
to scala-user
Today I found it is even weirder.
I didn't need to fill in continuations.enable in P and the Xplugin
reference to continuations.jar.
I did reset defaults and then run and it still worked.

Dave

unread,
Feb 21, 2012, 9:08:28 AM2/21/12
to scala-user
O no false statement. I didn't clean project so P and Xplugin are
still both needed

Mirco Dotta

unread,
Feb 21, 2012, 9:13:21 AM2/21/12
to Dave, scala-user
Hi Dave,

That's strange, but there may be a bug we don't know of. Would you mind discussing this
on the scala-ide-user ML?

Below is the link to the discussion

http://groups.google.com/group/scala-ide-user/browse_thread/thread/cd6c9a23fe099ab8

-- Mirco

Eric Kolotyluk

unread,
Feb 21, 2012, 11:40:51 AM2/21/12
to Mirco Dotta, scala...@googlegroups.com
Thanks for the reference - I have bookmarked it.

However, I was not able to get this to work until I set the path to the
continuations.jar in the -Xplugin field.

As I noted, there is a problem with spaces in path names (which should
not be a problem in the year 2012 with any software), and perhaps that
is why this did not work with -Xpluginsdir either. Should I create a
JIRA issue regarding this?

Cheers, Eric

Mirco Dotta

unread,
Mar 5, 2012, 4:26:17 AM3/5/12
to Eric Kolotyluk, scala...@googlegroups.com
Just for the record, the issue reported by both Eric and Dave concerning enabling continuations
in the Scala IDE for Eclipse has been fixed and the patch is already available on both the Scala
IDE 2.0.x nightly (which we will use to cut a 2.0.1 release really soon ;)) and Scala IDE Helium
nightly.

http://scala-ide.org/download/nightly.html

You can read the tutorial to learn how to successfully enable continuations in the Scala IDE

http://scala-ide.org/docs/tutorials/continuations-plugin/index.html

Thanks guys for the feedback and, please, keep reporting issues you see in the Scala IDE for Eclipse,
that's really the only way we can make your daily Scala hacking better and better :)

Cheers,
Mirco

Reply all
Reply to author
Forward
0 new messages