Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Self referencing a val during definition in scala

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.

like image 553
Brandon Ross Pollack Avatar asked Nov 29 '15 04:11

Brandon Ross Pollack


2 Answers

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)
like image 99
mattinbits Avatar answered Oct 12 '22 03:10

mattinbits


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?

like image 1
Christian Hirsch Avatar answered Oct 12 '22 04:10

Christian Hirsch