This is something that I found out in scala and it works and I can't figure out why, can anyone explain why this works?
Essentially I can use the reference to a val while I am still defining it (because my other objects/actors take it in as a parameter)
val backbone: ActorRef = context.actorOf(
F_BackBone.props(
context.actorOf(F_PictureHandler.props(backbone)),
context.actorOf(F_UserHandler.props(backbone)),
context.actorOf(F_PageProfileHandler.props(backbone))
)
)
I will get a compiler error if I don't explicitly define the type, which makes sense.
Note that in this specific case, although the code compiles, it will not behave correctly since, as suggested in comments on the other answer, the value of backbone
passed into the other actors is 'null'.
This example demonstrates this:
import akka.actor.{Props, Actor, ActorRef, ActorSystem}
class SenderReceiver(sendTo:ActorRef) extends Actor{
override def preStart(): Unit = {
self ! "Start"
}
def receive = {
case "Start" => sendTo ! "Hello"
case "Hello" => println("Received Hello")
}
}
object SenderReceiver {
def props(sendTo:ActorRef):Props = Props(new SenderReceiver(sendTo))
}
object Example extends App {
val system = ActorSystem()
val actor: ActorRef = system.actorOf(SenderReceiver.props(actor))
system.awaitTermination()
}
This yields the following (repeatedly, since the supervisor strategy tries to restart the actor):
[info] [ERROR] [12/01/2015 09:47:04.543] [default-akka.actor.default-dispatcher-9] [akka://default/user/$a] null
[info] java.lang.NullPointerException
[info] at SenderReceiver$$anonfun$receive$1.applyOrElse(example.scala:10)
[info] at akka.actor.Actor$class.aroundReceive(Actor.scala:467)
[info] at SenderReceiver.aroundReceive(example.scala:3)
[info] at akka.actor.ActorCell.receiveMessage(ActorCell.scala:516)
[info] at akka.actor.ActorCell.invoke(ActorCell.scala:487)
[info] at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:238)
[info] at akka.dispatch.Mailbox.run(Mailbox.scala:220)
[info] at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:397)
[info] at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
[info] at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
[info] at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
[info] at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
In functional programming languages recursive definitions are an important concept. Think for instance of the classic example of defining the factorial.
For the specific case of Scala, a very nice explanation was given in a post earlier this month: A variable used in its own definition?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With