Having read various posts on delayedInit, I was surprised to learn that it's actually called each time by the various subclasses during construction. I wasn't sure I believed this but then I made the test below. Anyhow, my question is that delayedInit sounded like a useful mechanism to drive some kind of final action from an abstract class (for example, perhaps notifying another object of creation complete). And this would make sense, if it were only called once.
But how can any kind of useful construct be made from a function if you risk it being called repeatedly without any other useful information being passed in it's parameters? How could I program it to only fire at the last level of construction, without necessarily knowing how deeply class A has been extended?
object LearnDelayedInit extends App {
class A extends DelayedInit {
def delayedInit(x: => Unit) {
x // call constructor code
println("delayed init called")
}
}
class B extends A {
println("Hello from B")
}
class C extends B {
println("hello from C")
}
val c = new C
}
Output:
Hello from B
delayed init called
hello from C
delayed init called
If you make the hierarchy out of traits and only the leaf type a class you will get the behavior you want:
object LearnDelayedInit extends App {
trait A extends DelayedInit {
def delayedInit(x: => Unit) {
x //call constructor code
println("delayed init called")
}
}
trait B extends A {
println("Hello from B")
}
class C extends B {
println("hello from C")
}
val c = new C
}
Only the initialization code for classes is wrapped and passed to delayedInit, traits have their initialization code run in the constructor as usual.
Here you go.
The future stuff is just for flair.
The basic idea is that the val done is initialized exactly once, in the initializer of C or whatever the bottom class is.
You have read the one question in The One Question FAQ, I suppose.
object Test extends App {
import java.util.concurrent.{ CountDownLatch => Latch }
trait FutureInit {
import concurrent._
import ExecutionContext.Implicits._
private var fs = future(())
def done: Boolean
val latch = new Latch(1)
def delayedInit(x: => Unit) {
fs = fs andThen {
case _ =>
x
if (done) { println("All done!") ; latch.countDown() }
}
}
}
class A extends DelayedInit with FutureInit {
println("Hello from A")
Thread sleep 500L
override val done = true
}
class B extends A {
println("Hello from B")
Thread sleep 500L
override val done = true
}
class C extends B {
println("hello from C")
Thread sleep 500L
override val done = true
}
val c = new C
c.latch.await()
println("Good bye.")
val b = new B
b.latch.await()
println("That's all, folks. Go home.")
}
Related
I am trying to create some general functionality which allows me to add code to be executed before and after the body of a Scala object (extended with the App trait) in a generic way - something akin to Scalatest's BeforeAndAfterAll but for general code execution.
I would love to figure out a way to do this via a trait but am coming up short - something like
trait MyBeforeAndAfter {
def before = println("I am executed before!")
def after = println("I am executed after!")
}
object MyApp extends App with MyBeforeAndAfter {
println("I am generic code in the body that's wrapped")
}
and the target output when running the App would be (key feature being the ordering):
I am executed before
I am generic code in the body that's wrapped
I am executed after
Two approaches I have considered but can't figure out how to do are:
Somehow pass the code in the object body to a function which takes care of the wrapping - but I don't know how I can get access to the code block as something which I could pass to a function. I have looked at both the App trait itself and Scalatest's BeforeAndAfterAll to see their approaches. The former appears to be controlled in the compiler. The latter, I'm in the fifth level of inception and it's not yet clear to me how it works.
Split the before and after into separate traits and mix them in, and while trait ordering is pretty straightforward, I don't see any way to annotate that a trait should be executed after the base / target object / class.
Gods of Stack Overflow... help?
Edit per Luis' question - basically why do you want to do this?
I was working with akka quite a bit to build recently and with akka there's a lot of ActorSystem setup / teardown boilerplate - grabbing things from configs, standing up the system etc and I was thinking of ways to clear out some of that boilerplate to make the unique parts of the main app more visible. I ran into some similar desires in some other contexts as well and I continued to think about whether there was a general way to clear out the boilerplate in a "clean" manner - meaning similar to the App trait (no overrides required, just mixin and go), but also enabling flexibility to execute code both before and after the block.
Standard approach would be to run the code not in the body of an object but in some method
trait MyBeforeAndAfter {
def before() = println("I am executed before!")
def after() = println("I am executed after!")
def run(): Unit
def main(args: Array[String]): Unit = {
before()
run()
after()
}
}
object MyApp extends MyBeforeAndAfter {
override def run(): Unit = {
println("I am generic code in the body that's wrapped")
}
}
Then if you run MyApp it will print
I am executed before!
I am generic code in the body that's wrapped
I am executed after!
If you really want to run code in the body of an object you can define macro annotation
import scala.annotation.StaticAnnotation
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
class beforeAndAfter extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro BeforeAndAfterMacro.impl
}
object BeforeAndAfterMacro {
def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
import c.universe._
annottees match {
case q"$mods object $tname extends { ..$earlydefns } with ..$parents { $self => ..$body }" :: Nil =>
val parents1 = parents :+ tq"MyBeforeAndAfter"
q"""$mods object $tname extends { ..$earlydefns } with ..$parents1 { $self =>
def run(): Unit = {
..$body
}
}"""
case _ =>
c.abort(c.enclosingPosition, "annottee must be an object")
}
}
}
#beforeAndAfter
object MyApp {
println("I am generic code in the body that's wrapped")
}
//Warning:scalac: object MyApp extends scala.AnyRef with MyBeforeAndAfter {
// def <init>() = {
// super.<init>();
// ()
// };
// def run(): Unit = println("I am generic code in the body that\'s wrapped")
//}
Here a similar approach from the of #DmytroMitin
The only difference is that this lets you customize and reuse before and foreach methods.
trait BeforeAndAfter {
def before(): Unit
def after(): Unit
}
trait Program { self: BeforeAndAfter =>
def run(args: List[String]): Unit
final def main(args: Array[String]): Unit = {
self.before()
run(args.toList)
self.after()
}
}
Which you can use like this:
trait MyBeforeAndAfter extends BeforeAndAfter {
override final def before(): Unit = {
println("Setup")
}
override final def after(): Unit = {
println("Clean up")
}
}
object MyApp extends Program with MyBeforeAndAfter {
override final def run(args: List[String]): Unit = {
println("Program")
}
}
You can see it running here.
You should use before and after as functions and then invoke them in the execute method. The execute method is taking custom function as input, and executes in certain order. This is a standard approach which works irrespective of whether you call it in main or in another class.
trait BeforeAfter {
def execute(myfunction : () => Unit) = {
before()
myfunction()
after()
}
def before() = println("before")
def after() = println("after")
}
object MyApp extends App with BeforeAfter{
def myprinter() = println("printing main")
execute(myprinter)
}
Results:
before
printing main
after
Given:
abstract class A { def show: Unit }
trait T extends A {
abstract override def show: Unit = {
print(" T"); super.show; print(" xT")
}
}
trait U extends A {
abstract override def show: Unit = {
print(" U"); super.show; print(" xU")
}
}
class C extends A {
def show: Unit = print(" C")
}
I can do:
new C with T with U show
But, it "feels" (given Scala's propensity for shortened syntaxes and anonymous stuff in general) like I might be able to instantiate my mixed in class from an anonymous form. Something on the lines of
// doesn't work like this at least:
val a = new { def show { print("Anon")}} with T with U
a show
But I have entirely failed to determine if I'm simply using the wrong syntax, or if this is simply not possible. Can someone tell me how this should be done, or if it definitely is not possible?
I don't think this is possible.
The following two proposals are as close as I can get.
Use Constructor with Mixins
The following solution requires an additional helper class D,
but the end result looks almost as your fictional syntax, except
that you need one additional character for D, and you have to
use round parentheses instead of curly braces:
import scala.language.postfixOps
abstract class A { def show: Unit }
trait T extends A {
abstract override def show: Unit = {
print(" T"); super.show; print(" xT")
}
}
trait U extends A {
abstract override def show: Unit = {
print(" U"); super.show; print(" xU")
}
}
class C extends A {
def show: Unit = print(" C")
}
new C with T with U show
class D(s: => Unit) extends A {
def show = s
}
// that's pretty close, isn't it?
val a = new D(print("hurray!")) with T with U
a show
Just hide the class in a block
If you just don't want to litter the namespace with classes that you use only once, then just enclose the class in a block:
val a = {
class D extends A {
def show = println("NoPollution")
}
new D with T with U
}
a show
What you wanted is to "eliminate the useless variable D" in the above "class-valued compile-time-evaluated-expression", but I don't see how one could do that.
Isn't this what you want?
val a = new T with U {override def show { print("Anon")}}
Syntax is pretty much the same as with declaring a new class, first the extensions/mixins, then the body.
Could you please explain why the following code is not working as expected.
The actor is not printing the message
Thanks.
class Base {
def f() = { "This is Base" }
}
class Sub extends Base {
override def f() = { "This is Sub" }
}
case class myCase(x: Base)
import scala.actors._
object myActor extends Actor {
def act()
{
loop {
react {
case myCase(x) => x.f()
case msg => "unknown"
}
}
}
def main(args: Array[String]): Unit = {
this ! myCase(new Base)
this ! myCase(new Sub)
}
}
Answering the question
The problem has nothing whatsoever to do with inheritance or case classes (I have re-titled the question to reflect this). The code does not print anything for two reasons:
Because your code does not actually make any calls to println! Replace:
case myCase(x) => x.f()
with
case myCase(x) => println( x.f() )
Because you do not start your actor. I think your program would make more sense if the actor were an inner class:
object myActor extends App {
class MyActor extends Actor {
def act() {
loop {
react {
... // <-- You need to print stuff
}
}
}
}
val a = new MyActor
a.start() // <-- You need to start it
a ! myCase(new Base)
a ! myCase(new Sub)
}
Advice: case classes and inheritance
I would, however, offer the advice that using inheritance in the presence of case classes is a bad idea. I usually use the approach of declaring common behaviour/state in a trait:
sealed trait Base {
def f(): Unit
}
case class Sub() extends Base
Why is it a bad idea? Well, one of the contracts that case-classes give you is a rigid definition of equivalence (that is, an equals and hashCode implementation). In the presence of inheritance, this could well be misleading. That is, your code will probably not do what you expect. Consider the following;
scala> abstract class Base { val x: Int }
defined class Base
scala> case class Sub(s: String) extends Base { val x = util.Random.nextInt(100) }
defined class Sub
Now if I create 2 instances...
scala> Sub("Hey")
res2: Sub = Sub(Hey)
scala> Sub("Hey")
res3: Sub = Sub(Hey)
They are equivalent
scala> res2 == res3
res4: Boolean = true
But they do not have the same state
scala> res2.x
res5: Int = 28
scala> res3.x
res7: Int = 15
Note, I am not saying this is a bug. I'm just saying it's an area where you might find that you introduce a bug in your code because you have made the assumption that any state of the case class is included in its equivalence.
trait A extends Actor {
private val s = Set[Int]()
override def act() {
loop {
react {
// case code that modifies s
}
}
}
}
trait B extends Actor {
private val t = Set[String]()
override def act() {
loop {
react {
// case code that modifies t
}
}
}
}
val c = new C with A with B //...?
What I really want is some sort of auto-combining of B.act() and C.act(), but with trait mix-ins, only B.act() will be called. Is there an easy way to accomplish this?
EDIT: Here is a half-solution I've found. I say 'half' because the original traits no longer extend Actor, and C with A with B needs to be defined as a class as opposed to dynamic mixing-in. Maybe I should call it a 'quarter-solution'?
Maybe you could make a trait that forwards the message on to a list of other Actors, so that you don't have to modify A or B:
trait C extends Actor {
private val acts: Seq[Actor] = Seq(new A{}, new B{})
override def act() {
acts foreach (_.start)
loop {
react { case x => acts foreach { _ ! x } }
}
}
}
You could of course leave acts abstract or override it with a different set when you instantiate this.
Extending the Actor class:
import actors.Actor
class MixableActor extends Actor {
protected var acts = List[PartialFunction[Any, Unit]]()
final override def act() {
loop {
react {
acts.reduce((a, b) => a orElse b)
}
}
}
final def receive(act: PartialFunction[Any, Unit]) {
acts = act :: acts
}
}
Sample Code:
abstract class Node extends MixableActor {
...
}
trait User extends MixableActor {
val files = scala.collection.mutable.Set[Data]()
}
trait Provider extends User {
receive({
case ("provide", file: Data) =>
provide(file)
}: PartialFunction[Any, Unit])
}
trait Consumer extends User {
receive({
case ("consume", file: Data) =>
consume(file)
}: PartialFunction[Any, Unit])
}
Sample Usage:
val provider = new Node with Provider
val consumer = new Node with Consumer
val provider_and_consumer = new Node with Provider with Consumer
I have a program structured as follows:
abstract class OuterClass
{
class InnerClass extends Actor
{
loop
{
react
{
case m: T => someFunction(m)
}
}
def someFunction(m: T)
{
...search function map for specific function...
specificFunction()
}
...extra methods here...
}
var functionmap=scala.sollection.mutable.Map.empty[String,()=>String]
var actorpool: ArrayBuffer[Actor]=new ArrayBuffer(0)
def main(args: Array[String])
{
...create X actors and add them to the pool...
populatefunctionmap
}
def populatefunctionmap() //defined elsewhere
}
class RunMe extends OuterClass
{
def populatefunctionmap()
{
...add some functions to the map...
}
}
The problem I have is that I would like to make use of the extra functions available within the actor instance that runs my functionmap functions. When I've tried using this it refers to the extending RunMe class. Using self just results in a not found: value self compiler error.
Is what I want to do possible? If so, how?
A couple of points I'd like to make about your code:
functionmap is both a var and mutable Map. Typically you only need it to be one or the other; not both.
Same goes for actorpool.
Access to shared, mutable state violates the design principles of the actor model.
Given the skeleton you provided, I'm assuming that you don't need to change the functionmap after it's been initialized. Instead of making it a mutable var, make it an immutable val.
You can do that by either an abstract val (shown here), or by a constructor parameter.
abstract class OuterClass {
class InnerClass extends Actor {
def act() {
loop {
react {
case m: T => someFunction(m)
}
}
}
def someFunction(m: T) {
// ...search functionmap for specific function...
for (specificFunction <- functionmap.get(key)) {
specificFunction()
}
}
}
// abstract val
val functionmap: Map[String, () => String]
val actorpool: ArrayBuffer[Actor]=new ArrayBuffer(0)
def main(args: Array[String]) {
// ...create X actors and add them to the pool...
}
}
class RunMe extends OuterClass {
val functionmap = {
// ...build the function map...
}
}
If you need to change functionmap after the actors are created, then InnerClass needs to have a var which holds their own functionmap, which you change by sending messages to the actors.
If I understand correctly, your question has nothing to do with Actors. It boils down to:
abstract class Outer {
class Inner {
def innerf = 42
}
}
class RunMe extends Outer {
val inst = new Inner
def ref = inst.innerf
}
scala> (new RunMe).ref
res0: Int = 42
scala> val r = new RunMe
scala> (new r.Inner).innerf
res1: Int = 42
The inner class's methods are only available on an instance of that inner class, so you need to start by making some instances.
If you'd like to access methods of InnerClass from the functions in functionmap, then it should be of type InnerClass => String, so you have the instance you want to call methods on.