=act #3572 Add parens to sender

* because it is not referentially transparent; normally we reserved parens for
  side-effecting code but given how people thoughtlessly close over it we revised
  that that decision for sender
* caller can still omit parens
This commit is contained in:
Patrik Nordwall 2014-01-16 15:16:35 +01:00
parent 537840bd2a
commit a11fb1dafc
202 changed files with 631 additions and 620 deletions

View file

@ -432,7 +432,7 @@ Messages can be sent via the :class:`ActorSelection` and the path of the
does not match any actors the message will be dropped.
To acquire an :class:`ActorRef` for an :class:`ActorSelection` you need to send
a message to the selection and use the ``sender`` reference of the reply from
a message to the selection and use the ``sender()`` reference of the reply from
the actor. There is a built-in ``Identify`` message that all Actors will
understand and automatically reply to with a ``ActorIdentity`` message
containing the :class:`ActorRef`. This message is handled specially by the
@ -517,8 +517,8 @@ message. This gives the best concurrency and scalability characteristics.
If invoked from within an Actor, then the sending actor reference will be
implicitly passed along with the message and available to the receiving Actor
in its ``sender: ActorRef`` member field. The target actor can use this
to reply to the original sender, by using ``sender ! replyMsg``.
in its ``sender(): ActorRef`` member method. The target actor can use this
to reply to the original sender, by using ``sender() ! replyMsg``.
If invoked from an instance that is **not** an Actor the sender will be
:obj:`deadLetters` actor reference by default.
@ -540,7 +540,7 @@ future to affect the submission of the aggregated :class:`Result` to another
actor.
Using ``ask`` will send a message to the receiving Actor as with ``tell``, and
the receiving actor must reply with ``sender ! reply`` in order to complete the
the receiving actor must reply with ``sender() ! reply`` in order to complete the
returned :class:`Future` with a value. The ``ask`` operation involves creating
an internal actor for handling this reply, which needs to have a timeout after
which it is destroyed in order not to leak resources; see more below.
@ -613,8 +613,8 @@ Reply to messages
=================
If you want to have a handle for replying to a message, you can use
``sender``, which gives you an ActorRef. You can reply by sending to
that ActorRef with ``sender ! replyMsg``. You can also store the ActorRef
``sender()``, which gives you an ActorRef. You can reply by sending to
that ActorRef with ``sender() ! replyMsg``. You can also store the ActorRef
for replying later, or passing on to other actors. If there is no sender (a
message was sent without an actor or future context) then the sender
defaults to a 'dead-letter' actor ref.
@ -623,7 +623,7 @@ defaults to a 'dead-letter' actor ref.
case request =>
val result = process(request)
sender ! result // will have dead-letter actor as default
sender() ! result // will have dead-letter actor as default
Receive timeout
===============

View file

@ -40,7 +40,7 @@ class FirstActor extends Actor {
val child = context.actorOf(Props[MyActor], name = "myChild")
//#plus-some-behavior
def receive = {
case x => sender ! x
case x => sender() ! x
}
//#plus-some-behavior
}
@ -64,7 +64,7 @@ class DemoActorWrapper extends Actor {
class DemoActor(magicNumber: Int) extends Actor {
def receive = {
case x: Int => sender ! (x + magicNumber)
case x: Int => sender() ! (x + magicNumber)
}
}
@ -91,7 +91,7 @@ class AnonymousActor extends Actor {
def receive = {
case DoIt(msg) =>
val replyMsg = doSomeDangerousWork(msg)
sender ! replyMsg
sender() ! replyMsg
context.stop(self)
}
def doSomeDangerousWork(msg: ImmutableMessage): String = { "done" }
@ -123,10 +123,10 @@ class ReplyException extends Actor {
//#reply-exception
try {
val result = operation()
sender ! result
sender() ! result
} catch {
case e: Exception =>
sender ! akka.actor.Status.Failure(e)
sender() ! akka.actor.Status.Failure(e)
throw e
}
//#reply-exception
@ -271,7 +271,7 @@ class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
"creating actor with IndirectActorProducer" in {
class Echo(name: String) extends Actor {
def receive = {
case n: Int => sender ! name
case n: Int => sender() ! name
case message =>
val target = testActor
//#forward
@ -365,12 +365,12 @@ class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
class HotSwapActor extends Actor {
import context._
def angry: Receive = {
case "foo" => sender ! "I am already angry?"
case "foo" => sender() ! "I am already angry?"
case "bar" => become(happy)
}
def happy: Receive = {
case "bar" => sender ! "I am already happy :-)"
case "bar" => sender() ! "I am already happy :-)"
case "foo" => become(angry)
}
@ -417,7 +417,7 @@ class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
def receive = {
case "kill" =>
context.stop(child); lastSender = sender
context.stop(child); lastSender = sender()
case Terminated(`child`) => lastSender ! "finished"
}
}
@ -522,12 +522,12 @@ class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
def receive = {
case ref: ActorRef =>
//#reply-with-sender
sender.tell("reply", context.parent) // replies will go back to parent
sender.!("reply")(context.parent) // alternative syntax (beware of the parens!)
sender().tell("reply", context.parent) // replies will go back to parent
sender().!("reply")(context.parent) // alternative syntax (beware of the parens!)
//#reply-with-sender
case x =>
//#reply-without-sender
sender ! x // replies will go to this actor
sender() ! x // replies will go to this actor
//#reply-without-sender
}
}
@ -585,13 +585,13 @@ class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
trait TheirComposableActor extends ComposableActor {
receiveBuilder += {
case "foo" => sender ! "foo received"
case "foo" => sender() ! "foo received"
}
}
class MyComposableActor extends TheirComposableActor {
receiveBuilder += {
case "bar" => sender ! "bar received"
case "bar" => sender() ! "bar received"
}
}
//#receive-orElse2

View file

@ -204,7 +204,7 @@ class CounterService extends Actor {
if (backlog.size >= MaxBacklog)
throw new ServiceUnavailable(
"CounterService not available, lack of initial value")
backlog :+= (sender -> msg)
backlog :+= (sender() -> msg)
}
}
@ -239,7 +239,7 @@ class Counter(key: String, initialValue: Long) extends Actor {
storeCount()
case GetCurrentCount =>
sender ! CurrentCount(key, count)
sender() ! CurrentCount(key, count)
}
@ -272,7 +272,7 @@ class Storage extends Actor {
def receive = LoggingReceive {
case Store(Entry(key, count)) => db.save(key, count)
case Get(key) => sender ! Entry(key, db.load(key).getOrElse(0L))
case Get(key) => sender() ! Entry(key, db.load(key).getOrElse(0L))
}
}

View file

@ -34,7 +34,7 @@ object FaultHandlingDocSpec {
//#strategy
def receive = {
case p: Props => sender ! context.actorOf(p)
case p: Props => sender() ! context.actorOf(p)
}
}
//#supervisor
@ -56,7 +56,7 @@ object FaultHandlingDocSpec {
//#strategy2
def receive = {
case p: Props => sender ! context.actorOf(p)
case p: Props => sender() ! context.actorOf(p)
}
// override default to kill all children during restart
override def preRestart(cause: Throwable, msg: Option[Any]) {}
@ -87,7 +87,7 @@ object FaultHandlingDocSpec {
def receive = {
case ex: Exception => throw ex
case x: Int => state = x
case "get" => sender ! state
case "get" => sender() ! state
}
}
//#child

View file

@ -44,7 +44,7 @@ object InitializationDocSpec {
}
def initialized: Receive = {
case "U OK?" => initializeMe foreach { sender ! _ }
case "U OK?" => initializeMe foreach { sender() ! _ }
}
//#messageInit

View file

@ -28,7 +28,7 @@ object Consumers {
def endpointUri = "jetty:http://localhost:8877/camel/default"
def receive = {
case msg: CamelMessage => sender ! ("Hello %s" format msg.bodyAs[String])
case msg: CamelMessage => sender() ! ("Hello %s" format msg.bodyAs[String])
}
}
//#Consumer2
@ -46,12 +46,12 @@ object Consumers {
def receive = {
case msg: CamelMessage =>
sender ! Ack
sender() ! Ack
// on success
// ..
val someException = new Exception("e1")
// on failure
sender ! Failure(someException)
sender() ! Failure(someException)
}
}
//#Consumer3
@ -65,7 +65,7 @@ object Consumers {
def endpointUri = "jetty:http://localhost:8877/camel/default"
override def replyTimeout = 500 millis
def receive = {
case msg: CamelMessage => sender ! ("Hello %s" format msg.bodyAs[String])
case msg: CamelMessage => sender() ! ("Hello %s" format msg.bodyAs[String])
}
}
//#Consumer4

View file

@ -19,7 +19,7 @@ object CustomRoute {
class Responder extends Actor {
def receive = {
case msg: CamelMessage =>
sender ! (msg.mapBody {
sender() ! (msg.mapBody {
body: String => "received %s" format body
})
}
@ -53,7 +53,7 @@ object CustomRoute {
handled(true).transform(Builder.exceptionMessage).end
final override def preRestart(reason: Throwable, message: Option[Any]) {
sender ! Failure(reason)
sender() ! Failure(reason)
}
}
//#ErrorThrowingConsumer

View file

@ -120,7 +120,7 @@ object Producers {
def receive = {
case msg =>
val template = CamelExtension(context.system).template
sender ! template.requestBody("direct:news", msg)
sender() ! template.requestBody("direct:news", msg)
}
}
//#RequestProducerTemplate

View file

@ -27,7 +27,7 @@ object PublishSubscribe {
def receive = {
case msg: CamelMessage => {
publisher ! msg.bodyAs[String]
sender ! ("message published")
sender() ! ("message published")
}
}
}

View file

@ -85,7 +85,7 @@ object LoggingDocSpec {
class MyEventListener extends Actor {
def receive = {
case InitializeLogger(_) => sender ! LoggerInitialized
case InitializeLogger(_) => sender() ! LoggerInitialized
case Error(cause, logSource, logClass, message) => // ...
case Warning(logSource, logClass, message) => // ...
case Info(logSource, logClass, message) => // ...

View file

@ -18,9 +18,9 @@ object FutureDocSpec {
class MyActor extends Actor {
def receive = {
case x: String => sender ! x.toUpperCase
case x: Int if x < 0 => sender ! Status.Failure(new ArithmeticException("Negative values not supported"))
case x: Int => sender ! x
case x: String => sender() ! x.toUpperCase
case x: Int if x < 0 => sender() ! Status.Failure(new ArithmeticException("Negative values not supported"))
case x: Int => sender() ! x
}
}
@ -30,7 +30,7 @@ object FutureDocSpec {
var n = 1
def receive = {
case GetNext =>
sender ! n
sender() ! n
n += 2
}
}

View file

@ -63,8 +63,8 @@ class EchoManager(handlerClass: Class[_]) extends Actor with ActorLogging {
//#echo-manager
case Connected(remote, local) =>
log.info("received connection from {}", remote)
val handler = context.actorOf(Props(handlerClass, sender, remote))
sender ! Register(handler, keepOpenOnPeerClosed = true)
val handler = context.actorOf(Props(handlerClass, sender(), remote))
sender() ! Register(handler, keepOpenOnPeerClosed = true)
//#echo-manager
}

View file

@ -46,7 +46,7 @@ class Server extends Actor {
context.parent ! c
//#server
val handler = context.actorOf(Props[SimplisticHandler])
val connection = sender
val connection = sender()
connection ! Register(handler)
}
@ -57,7 +57,7 @@ class Server extends Actor {
class SimplisticHandler extends Actor {
import Tcp._
def receive = {
case Received(data) => sender ! Write(data)
case Received(data) => sender() ! Write(data)
case PeerClosed => context stop self
}
}
@ -83,7 +83,7 @@ class Client(remote: InetSocketAddress, listener: ActorRef) extends Actor {
case c @ Connected(remote, local) =>
listener ! c
val connection = sender
val connection = sender()
connection ! Register(self)
context become {
case data: ByteString =>

View file

@ -22,9 +22,9 @@ object ScalaUdpDocSpec {
def receive = {
case Udp.SimpleSenderReady =>
context.become(ready(sender))
context.become(ready(sender()))
//#sender
sender ! Udp.Send(ByteString("hello"), remote)
sender() ! Udp.Send(ByteString("hello"), remote)
//#sender
}
@ -48,7 +48,7 @@ object ScalaUdpDocSpec {
//#listener
nextActor forward local
//#listener
context.become(ready(sender))
context.become(ready(sender()))
}
def ready(socket: ActorRef): Receive = {
@ -72,9 +72,9 @@ object ScalaUdpDocSpec {
def receive = {
case UdpConnected.Connected =>
context.become(ready(sender))
context.become(ready(sender()))
//#connected
sender ! UdpConnected.Send(ByteString("hello"))
sender() ! UdpConnected.Send(ByteString("hello"))
//#connected
}

View file

@ -13,7 +13,7 @@ import akka.remote.RemoteScope
object RemoteDeploymentDocSpec {
class SampleActor extends Actor {
def receive = { case _ => sender ! self }
def receive = { case _ => sender() ! self }
}
}

View file

@ -19,7 +19,7 @@ object ConsistentHashingRouterDocSpec {
def receive = {
case Entry(key, value) => cache += (key -> value)
case Get(key) => sender ! cache.get(key)
case Get(key) => sender() ! cache.get(key)
case Evict(key) => cache -= key
}
}

View file

@ -58,7 +58,7 @@ akka.actor.deployment {
class Storage extends Actor {
def receive = {
case x => sender ! x
case x => sender() ! x
}
}

View file

@ -197,7 +197,7 @@ router-dispatcher {}
def receive = {
case w: Work =>
router.route(w, sender)
router.route(w, sender())
case Terminated(a) =>
router = router.removeRoutee(a)
val r = context.actorOf(Props[Worker])
@ -375,7 +375,7 @@ router-dispatcher {}
class Echo extends Actor {
def receive = {
case m => sender ! m
case m => sender() ! m
}
}
}

View file

@ -16,7 +16,7 @@ import akka.testkit.ImplicitSender
object MySpec {
class EchoActor extends Actor {
def receive = {
case x => sender ! x
case x => sender() ! x
}
}
}

View file

@ -117,7 +117,7 @@ object TestKitUsageSpec {
*/
class EchoActor extends Actor {
def receive = {
case msg => sender ! msg
case msg => sender() ! msg
}
}

View file

@ -22,8 +22,8 @@ object TestkitDocSpec {
class MyActor extends Actor {
def receive = {
case Say42 => sender ! 42
case "some work" => sender ! "some result"
case Say42 => sender() ! 42
case "some work" => sender() ! "some result"
}
}
@ -201,7 +201,7 @@ class TestkitDocSpec extends AkkaSpec with DefaultTimeout with ImplicitSender {
expectMsgPF() {
case Update(id, _) if id == x => true
}
sender ! "ACK"
sender() ! "ACK"
}
}
//#test-special-probe

View file

@ -39,7 +39,7 @@ Some examples
If you schedule functions or Runnable instances you should be extra careful
to not close over unstable references. In practice this means not using ``this``
inside the closure in the scope of an Actor instance, not accessing ``sender`` directly
inside the closure in the scope of an Actor instance, not accessing ``sender()`` directly
and not calling the methods of the Actor instance directly. If you need to
schedule an invocation schedule a message to ``self`` instead (containing the
necessary parameters) and then call the method when the message is received.