Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Responder.run does not work with Futures #3458

Closed
scabug opened this issue May 20, 2010 · 3 comments
Closed

Responder.run does not work with Futures #3458

scabug opened this issue May 20, 2010 · 3 comments
Assignees

Comments

@scabug
Copy link

scabug commented May 20, 2010

Calling Responder.run on Futures does not work.

Running this

import actors.Actor._
import actors.Futures._
import Responder._

println("Result:" + run( constant(42) ) )

println("Result: " +  run( future{Thread.sleep(1000); 42} ) )

actor{ println("Result: " +  run( future{Thread.sleep(1000); 42} ) ) }

in the REPL yields

Welcome to Scala version 2.8.0.RC2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_20).

scala> import actors.Actor._
scala> import actors.Futures._
scala> import Responder._

scala> println("Result:" + run( constant(42) ) )
Result:Some(42)

scala> println("Result: " +  run( future{Thread.sleep(1000); 42} ) )
scala.actors.SuspendActorControl

scala.actors.ActorProxy@2026c088: caught java.lang.InterruptedException
java.lang.InterruptedException
	at scala.actors.ActorProxy.exit(ActorProxy.scala:33)
	at scala.actors.Reactor$$$$anonfun$$2.apply(Reactor.scala:253)
	at scala.actors.Reactor$$$$anonfun$$2.apply(Reactor.scala:253)
    ...

scala> actor{ println("Result: " +  run( future{Thread.sleep(1000); 42} ) ) }
res3: scala.actors.Actor = scala.actors.Actor$$$$anon$$1@69beea90
    ... NO OUTPUT ...

So running the future works neither in the main thread, nor inside an
actor. This is because Responder.run calls respond on the future,
which never returns for Futures:

object Responder {
  ...
  def run[A](r: Responder[A]): Option[A] = {
    var result: Option[A] = None
    r.foreach(x => result = Some(x))
    result
  }
  ...
}

abstract class Responder[+A] {
  ...
  def foreach(k: A => Unit) { respond(k) }
  ...
}

An ugly workaround would be to define

def run2[A](r: Responder[A]): Option[A] = r match {
  case f: actors.Future[_] => Some[A](f())
  case r => run(r)
}

using apply() in case of futures. Then this works:

scala> println("Result: " +  run2( future{Thread.sleep(1000); 42} ) )
Result: Some(42)

Proposed solution:

Obviously, run needs to do different things for different kinds
of Responders. But actually, Future provides the same functionality
with apply() that Responder.run() does for "normal" Responders.

An elegant solution would be to simply add an apply() method
to Responder, too, and have Responder.run just call apply on
the responder in question:

object Responder {
  ...
  def run[A](r: Responder[A]): Option[A] = Option(r())
  ...
}

abstract class Responder[+A] {
  ...
  def apply(): A = {
    var result: Option[A] = None
    r.foreach(x => result = Some(x))
    result orNull
  }
  ...
}

I'm not sure if the Option stuff in apply is strictly necessary, I just tried to preserve the current implementation of run as much as possible.

This would require very litte code changes. It also shouldn't break anything, should it?

@scabug
Copy link
Author

scabug commented May 20, 2010

Imported From: https://issues.scala-lang.org/browse/SI-3458?orig=1
Reporter: @oschulz

@scabug
Copy link
Author

scabug commented May 21, 2010

@oschulz said:
On second thought, apply() returning null wasn't such a bright
idea - sorry. So, I propose this instead:

class NoResponse(msg: String) extends RuntimeException(msg)

object Responder {
  ...
  def run[A](r: Responder[A]): Option[A] = {
    try { Some(r()) }
    catch { case e: NoResponse => None }
  }
  ...
}

abstract class Responder[+A] {
  ...
  def apply(): A = {
    var result: Option[A] = None
    foreach { x => result = Some(x) }
    result getOrElse { throw new NoResponse("NoResponse") }
  }
  ...
}

@scabug
Copy link
Author

scabug commented Jul 17, 2015

@SethTisue said:
Scala actors are deprecated and unmaintained

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants