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.
Related
I'm using two Scala libraries that both rely on implicit parameters to supply codecs/marshallers for case classes (the libraries in question are msgpack4s and op-rabbit). A simplified example follows:
sealed abstract trait Event
case class SomeEvent(msg: String) extends Event
case class OtherEvent(code: String) extends Event
// Assume library1 needs Show and library2 needs Printer
trait Show[A] { def show(a: A): String }
trait Printer[A] { def printIt(a: A): Unit }
object ShowInstances {
implicit val showSomeEvent = new Show[SomeEvent] {
override def show(a: SomeEvent) =
s"SomeEvent: ${a.msg}"
}
implicit val showOtherEvent = new Show[OtherEvent] {
override def show(a: OtherEvent) =
s"OtherEvent: ${a.code}"
}
}
The Printer for the one library can be generic provided there's an implicit Show for the other library available:
object PrinterInstances {
implicit def somePrinter[A: Show]: Printer[A] = new Printer[A] {
override def printIt(a: A): Unit =
println(implicitly[Show[A]].show(a))
}
}
I want to provide an API that abstracts over the details of the underlying libraries - callers should only need to pass the case class, internally to the API implementation the relevant implicits should be summoned.
object EventHandler {
private def printEvent[A <: Event](a: A)(implicit printer: Printer[A]): Unit = {
print("Handling event: ")
printer.printIt(a)
}
def handle(a: Event): Unit = {
import ShowInstances._
import PrinterInstances._
// I'd like to do this:
//EventHandler.printEvent(a)
// but I have to do this
a match {
case s: SomeEvent => EventHandler.printEvent(s)
case o: OtherEvent => EventHandler.printEvent(o)
}
}
}
The comments in EventHandler.handle() method indicate my issue - is there a way to have the compiler select the right implicits for me?.
I suspect the answer is no because at compile time the compiler doesn't know which subclass of Event handle() will receive, but I wanted to see if there's another way. In my actual code, I control & can change the PrinterInstances code, but I can't change the signature of the printEvent method (that's provided by one of the libraries)
*EDIT: I think this is the same as Provide implicits for all subtypes of sealed type. The answer there is nearly 2 years old, I'm wondering if it's still the best approach?
You have to do the pattern matching somewhere. Do it in the Show instance:
implicit val showEvent = new Show[Event] {
def show(a: Event) = a match {
case SomeEvent(msg) => s"SomeEvent: $msg"
case OtherEvent(code) => s"OtherEvent: $code"
}
}
If you absolutely need individual instances for SomeEvent and OtherEvent, you can provide them in a different object so they can be imported separately.
If Show is defined to be contravariant (i.e. as trait Show[-A] { ... }, with a minus on the generic type) then everything works out of the box and a Show[Event] is usable as a Show[SomeEvent] (and as a Show[OtherEvent] for that matter).
If Show is unfortunately not written to be contravariant, then we might have to do a little bit more juggling on our end than we'd like. One thing we can do is declare all of our SomeEvent values as simply Events, vis a vis val fooEvent: Event = SomeEvent("foo"). Then fooEvent will be showable.
In a more extreme version of the above trick, we can actually hide our inheritance hierarchy:
sealed trait Event {
def fold[X]( withSomeEvent: String => X,
withOtherEvent: String => X ): X
}
object Event {
private case class SomeEvent(msg: String) extends Event {
def fold[X]( withSomeEvent: String => X,
withOtherEvent: String => X ): X = withSomeEvent(msg)
}
private case class OtherEvent(code: String) extends Event {
def fold[X]( withSomeEvent: String => X,
withOtherEvent: String => X ): X = withOtherEvent(code)
}
def someEvent(msg: String): Event = SomeEvent(msg)
def otherEvent(code: String): Event = OtherEvent(code)
}
Event.someEvent and Event.otherEvent allow us to construct values, and fold allows us to pattern match.
I've made an enum macro, which ended up having a strange behavior.
This is the main implementation:
object Enum {
def values[A]: Seq[A] = macro Impl.values[A]
class Impl(val c: Context) {
import c.universe._
def values[A: c.WeakTypeTag]: c.Expr[A] = {
val elemType = weakTypeOf[A]
val elemSymbol = elemType.typeSymbol.asSealedClass
val elemSymbols = elemSymbol.knownDirectSubclasses.toList
val elemIdents = elemSymbols.map(s => Ident(s.asCaseClass.asModuleClass.module))
val elemSeqSymbol = weakTypeOf[Seq[A]].typeSymbol
c.Expr(Apply(Ident(elemSeqSymbol.companion), elemIdents))
}
implicit class SymbolOp(s: Symbol) {
def asSealedClass = s.asClass.ensuring(_.isSealed, s"$s is not sealed")
def asCaseClass = s.asClass.ensuring(_.isCaseClass, s"$s is not a case class")
def asModuleClass = s.asClass.ensuring(_.isModuleClass, s"$s is not an object")
}
}
}
And this is the test:
object EnumTest extends App {
sealed trait Foo
case object Moo extends Foo
case object Noo extends Foo
val values = Enum.values[Foo]
println(values)
println(Enum.values[Foo])
println({
val v = Enum.values[Foo]
v
})
}
The console should print out three same outputs, but:
List()
List(Moo, Noo)
List(Moo, Noo)
Wny does this happen? How do you deal with this?
I would appreciate if you can test it in your SBT: https://github.com/ryo0ka/enum
Thank you!
This is indeed a strange behavior, but it is hard for Scalac to do a good job here: The problem is that you use nested objects. Consider the following:
object EnumTest extends App {
sealed trait Foo
case object Moo extends Foo
case object Noo extends Foo
println(Enum.values[Foo])
case object Bar extends Foo
}
This prints List(Moo, Noo). If we move Bar before the println statement, it prints List(Moo, Noo, Bar) as we would expect.
If we move the sealed hierarchy out of the object, everything works fine.
Therefore, it seems it is probably not a smart idea to have the macro reify at the location where you define your case classes. You could make values itself a macro (whose implementation simply calls Impl.values with the right WeakTypeTag). That would probably work.
Using scala 2.10.3, my goal is to make the following work:
object A {
implicit class Imp(i: Int) {
def myPrint() {
println(i)
}
}
}
object B {
implicit class Imp(i: String) {
def myPrint() {
println(i)
}
}
}
import A._
import B._
object MyApp extends App {
3.myPrint()
}
This fails with
value myPrint is not a member of Int
If I give A.Imp and B.Imp different names (for example A.Imp1 and B.Imp2), it works.
Diving a bit deeper into it, there seems to be the same problem with implicit conversions.
This works:
object A {
implicit def Imp(i: Int) = new {
def myPrint() {
println(i)
}
}
implicit def Imp(i: String) = new {
def myPrint() {
println(i)
}
}
}
import A._
object MyApp extends App {
3.myPrint()
}
Whereas this doesn't:
object A {
implicit def Imp(i: Int) = new {
def myPrint() {
println(i)
}
}
}
object B {
implicit def Imp(i: String) = new {
def myPrint() {
println(i)
}
}
}
import A._
import B._
object MyApp extends App {
3.myPrint()
}
Why? Is this a bug in the scala compiler? I need this scenario, since my objects A and B derive from the same trait (with a type parameter) which then defines the implicit conversion for its type parameter. In this trait, I can only give one name for the implicit conversion. I want to be able to import more of these objects into my scope. Is there a way to do that?
edit: I can't give the implicit classes different names, since the examples above are only breaking down the problem. My actual code looks more like
trait P[T] {
implicit class Imp(i: T) {
def myPrint() {
...
}
}
}
object A extends P[Int]
object B extends P[String]
import A._
import B._
The implicits just have to be available as a simple name, so you can rename on import.
Just to verify:
scala> import A._ ; import B.{ Imp => BImp, _ }
import A._
import B.{Imp=>BImp, _}
scala> 3.myPrint
3
Actually, it works if you replace
import A._
import B._
with
import B._
import A._
What happens, I think, is that A.Imp is shadowed by B.Imp because it has the same name. Apparently shadowing applies on the function's name and do not take the signature into account.
So if you import A then B, then only B.Imp(i: String) will be available, and if you import B then A, then only A.Imp(i: Int) will be available.
If you need to use both A.Imp and B.Imp, you must rename one of them.
In case anyone else runs into this issue, there is a partial workaround, which I found here:
https://github.com/lihaoyi/scalatags/blob/3dea48c42c5581329e363d8c3f587c2c50d92f85/scalatags/shared/src/main/scala/scalatags/generic/Bundle.scala#L120
That code was written by Li Haoyi, so you can be pretty confident that no better solution exists...
Essentially, one can still use traits to define methods in terms of each other, but it will require boilerplate to copy those implicits into unique names. This example might be easier to follow:
trait Chainable
object Chainable {
implicit val _chainableFromInt = IntChainable.chainable _
implicit val _chainableFromIntTrav = IntChainable.traversable _
implicit val _chainableFromIntOpt = IntChainable.optional _
implicit val _chainableFromIntTry = IntChainable.tried _
implicit val _chainableFromDom = DomChainable.chainable _
implicit val _chainableFromDomTrav = DomChainable.traversable _
implicit val _chainableFromDomOpt = DomChainable.optional _
implicit val _chainableFromDomTry = DomChainable.tried _
private object IntChainable extends ImplChainables[Int] {
def chainable(n:Int) = Constant(n)
}
private object DomChainable extends ImplChainables[dom.Element]{
def chainable(e:Element) = Insertion(e)
}
private trait ImplChainables[T] {
def chainable(t:T):Chainable
def traversable(trav:TraversableOnce[T]):Chainable =
SeqChainable(trav.map(chainable).toList)
def optional(opt:Option[T]):Chainable =
opt match {
case Some(t) => chainable(t)
case None => NoneChainable
}
def tried(tried:Try[T]):Chainable =
optional(tried.toOption)
}
}
In other words, never write:
trait P[T] {
implicit def foo(i: T) = ...
}
object A extends P[X]
Because defining implicits in type parameterized traits will lead to these naming conflicts. Although, incidentally, the trait in mentioned in the link above is parameterized over many types, but idea there is that none of the implementations of that trait are ever needed in the same scope. (JSDom vs Text, and all._ vs short._ for those familiar with Scalatags)
I also recommend reading: http://www.lihaoyi.com/post/ImplicitDesignPatternsinScala.html
It does not address this issue specifically but is an excellent summary of how to use implicits.
However, putting all these pieces together, this still seems to be an issue:
trait ImplChainables[AnotherTypeClass]{
type F[A] = A=>AnotherTypeClass
implicit def transitiveImplicit[A:F](t: A):Chainable
implicit def traversable[A:F](trav: TraversableOnce[A]):Chainable = ...
}
What this trait would allow is:
object anotherImpl extends ImplChainables[AnotherTypeClass] {...}
import anotherImpl._
implicit val string2another: String=>AnotherTypeClass = ...
Seq("x"):Chainable
Because of the type parameter and the context binding (implicit parameter) those cannot be eta-expanded (i.e: Foo.bar _ ) into function values. The implicit parameter part has been fixed in Dotty: http://dotty.epfl.ch/blog/2016/12/05/implicit-function-types.html
I do not know if a complete solution would be possible, needless to say this is a complex problem. So it would be nice if same name implicits just worked and the whole issue could be avoided. And in any case, adding an unimport keyword would make so much more sense than turning off implicits by shadowing them.
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.")
}
I'm using the Akka actors library here. The actors library defines a partial function "receive" which an actor that extends "actor" must implement to deal with various messages. I am creating a trait hierarchy for my application where trait "clockActor" extends Actor and "MasterClock" and "SubClock" extend "clockActor". I'm looking to add the common functionality of clocks in to the "clock" trait's receive function but then how to I add extra functionality to the receive function in the master and sub clock traits?
In short, I need a way to add extra case statements to a partial function.
Ideas?
As already suggested, you could easily compose PartialFunctions using orElse
trait ClockActor {
def commonOp = {
case ... => ...
}
}
class MasterClock extends Actor with ClockActor {
def receive = commonOp orElse masterOp
def masterOp = {
case ... => ...
}
}
class SubClock extends Actor with ClockActor {
def receive = commonOp orElse subOp
def subOp = {
case ... => ...
}
}
One thing that comes to mind is to do something like this:
trait ClockActor {
def pf:PartialFunction[String, Boolean] = {
case "a" => true
case v if(_pf.isDefinedAt(v)) => _pf.apply(v)
}
def _pf:PartialFunction[String, Boolean] = Map.empty
}
object MasterClock extends ClockActor {
override def _pf:PartialFunction[String, Boolean] = {
case "b" => false
}
println(pf("a"))
println(pf("b"))
}
which will output:
scala> MasterClock
true
false
The value true comes from the definition in the partial function of the Trait ClockActor, the falsecomes from the Object MasterClock.