Reputation: 112857
We have code like this scattered throughout our code base:
def receive: Receive = {
case x: TypeX => doXishThingsWith(x)
case y: TypeY => doYishThingsWith(y)
case z: TypeZ => doZishThingsWith(z)
}
I find the need to give names to x
, y
and z
kind of dumb and confusing.
I was wondering if something like this would work?
def receive: Receive = {
case TypeX => doXishThingsWith(_)
case TypeY => doYishThingsWith(_)
case TypeZ => doZishThingsWith(_)
}
I have no idea if _
actually works this way. But maybe there is something similar?
Upvotes: 2
Views: 778
Reputation: 8481
you can do classical polymorphism:
trait T{
def doThings()
}
class TypeX extends T{
override def doThings() {
println("doXishThingsWith")
}
}
class TypeY extends T{
override def do Things() {
println("doYishThingsWith")
}
}
def receive: Receive = {
case x: T => x.doThings()
}
using underscore in pattern matching just means throw that value away and do not make it accessible from any variable
Upvotes: 2
Reputation: 38045
No. case a: A => m(a)
is the shortest solution.
With case TypeX
you are trying to match on companion object of TypeX
, so you have to use underscore or variable name: case _: TypeX
.
With case _: TypeX
you have no access to variable.
Actually you could use methods without variable names using some magic like this:
def receive: Receive = (
pf[TypeX](doXishThingsWith) orElse
pf[TypeY](doYishThingsWith) orElse
pf[TypeZ](doZishThingsWith)
)
You have to create method pf
like this:
import reflect.{ClassTag, classTag}
def pf[T: ClassTag](f: T => _): PartialFunction[Any, Unit] = {
case e if classTag[T].runtimeClass.isInstance(e) => f(e.asInstanceOf[T])
}
Example:
class A; class B; class C
def mA(a: A) = println(s"mA!")
def mB(b: B) = println(s"mB!")
val receive = pf(mA) orElse pf(mB)
scala> receive.lift(new A)
mA!
res0: Option[Unit] = Some(())
scala> receive.lift(new B)
mB!
res1: Option[Unit] = Some(())
scala> receive.lift(new C)
res2: Option[Unit] = None
Upvotes: 6