Scala pattern matching type with inherited classes - scala

I have a series of inherited classes,with some more methods than the base class. Like this:
class Animal
{
var Name: String
}
class Fish extends Animal
{
def swim()
{
println("I'm a Fish and i'm swimming!");
}
}
class Turtle extends Animal
{
def swim()
{
println("I'm a Turtle and i'm swimming!");
}
}
I would like to use the type match pattern to a generic Animal class, to recognize the exact type and apply the swim() method if it can, like this:
myAnimal match {
case m:Fish => m.Swim()
case m:Turtle => m.Swim()
case _: => doSomethingElse()
}
I would like to write it in an elegant way, avoiding to repeat continuously the lines.
I know that I can do this:
myAnimal match {
case (_:Fish | _:Turtle) => println("I can do this!")
}
And I know, as I wrote above, that I can do:
myAnimal match {
case m:Fish => m.swim()
}
but, I can't put them in or, like this
myAnimal match {
case (m:Fish | m:Turtle) => m.swim() //ERROR (cannot recognize swim() method)
//Not even this
case m # (_:Fish | _:Turtle) => m.swim() //ERROR (cannot recognize swim() method)
case _: => doSomethingElse()
}
A good solution would be to insert an intermediate class, like AnimalsThatCanSwim that extend Animals. This solution should be the last option, because I have to avoid changing the extended classes.

You can use structural types combined with an extractor that uses reflection to check if your object has a swim method. Thanks to Mateusz Kubuszok and Dmytro Mitin, I now have a solution that seems to work.
Use like this:
myAnimal match {
case CanSwim(m) => m.swim()
case _ => println("Boohoo, I can't swim!")
}
The other stuff:
import scala.reflect.runtime.universe._
type CanSwim = { def swim(): Unit }
object CanSwim {
def unapply(arg: Any): Option[CanSwim] = {
try {
var res: Option[CanSwim] = None
for (symb <- runtimeMirror(arg.getClass.getClassLoader)
.reflect(arg)
.symbol
.info
.member(TermName("swim")) //get all methods named swim
.asTerm
.alternatives) { //alternatives because it might be overloaded
if (symb.isMethod) {
val msymb = symb.asMethod
//Check if the signature matches (Returns Unit and has 1 empty parameter list)
if (msymb.returnType =:= typeOf[Unit] && msymb.paramLists == List(List()))
res = Some(arg.asInstanceOf[CanSwim])
}
}
res
} catch {
case _ => None
//Might want to change this, but I don't think it's necessary to handle or throw exceptions
//If it failed, it probably means it can't swim
}
}
}
Link to Scastie
However, I really wouldn't recommend it. It's probably just easier to refactor your code.
<script src="https://scastie.scala-lang.org/gFBe7jTQQiW3WnPVTJoFPw.js"></script>

Related

How to write a custom decoder for [Option[Option[A]] in Circe?

I had written a Reads converter in play-json for Option[Option[A]] that had the following behavior:
//given this case class
case class MyModel(field: Option[Option[String]])
//this JSON -- maps to --> this MyModel:
//"{ \"field\": \"value\" }" --> MyModel(field = Some(Some("value")))
//"{ \"field\": null, ... }" --> MyModel(field = Some(None))
//"{ }" --> MyModel(field = None)
So, providing the value mapped to Some[Some[A]], providing null mapped to Some[None] (i.e. Some[Option.empty[A]]), and not providing the value mapped to just None (i.e. Option.empty[Option[A]]). Here's the play-json converter:
def readOptOpt[A](implicit r: Reads[A]): Reads[Option[Option[A]]] = {
Reads[Option[Option[A]]] { json =>
path.applyTillLast(json).fold(
identity,
_.fold(_ => JsSuccess(None), {
case JsNull => JsSuccess(Some(None))
case js => r.reads(js).repath(path).map(a => Some(Some(a)))
})
)
}
}
Now I am converting my play-json code to Circe, but I can't figure out how to write a Decoder[Option[Option[A]] that has the same behavior. That is, I need
def optOptDecoder[A](implicit d: Decoder[A]): Decoder[Option[Option[A]] = ??? //help!
Any ideas on how I can make this work? Thanks
I figured this out:
There were two problems:
1) How to deal with the case where the field was completely missing from the JSON. Turns out you have to use Decoder.reattempt in your custom decoder, following Circe's decodeOption code, which works.
2) How to have the compiler recognize cases of Option[Option[A]] when your decoder code is sitting in a helper object (or wherever). Turns out if you're using semi-auto derivation, you can create an implicit in the companion object and that will override the defaults:
//companion object
object MyModel {
implicit def myModelOptOptDecoder[A](implicit d: Decoder[A]): Decoder[Option[Option[A]]] =
MyHelperObject.optOptDecoder
implicit val myModelDecoder: Decoder[MyModel] = deriveDecoder
}
Anyway, I don't think this will be much help to anybody in the future, so unless I get any upvotes in the next few hours I think I'll just delete this.
Edit2: Okay it was answered so I won't delete it. Stay strong, esoteric circe question, stay strong...
An Option[Option[A]] is a bit odd. I understand and mostly agree with the reasoning, but I think it's weird enough that it may warrant just replacing it with your own class (and writing a decoder for that). Something like:
sealed trait OptionalNull[+A] {
def toOption: Option[Option[A]]
}
object NotPresent extends OptionalNull[Nothing] {
override def toOption = None
}
object PresentButNull extends OptionalNull[Nothing] {
override def toOption = Some(None)
}
case class PresentNotNull[A](value: A) extends OptionalNull[A] {
override def toOption = Some(Some(value))
}
This has the additional benefit of not having to worry about implicit precedence and stuff like that. Might simplify your decoder.
Here is another solution I found (This is not my gist):
sealed trait UpdateOrDelete[+A]
case object Delete extends UpdateOrDelete[Nothing]
final case class UpdateOptionalFieldWith[A](value: A) extends UpdateOrDelete[A]
object UpdateOrDelete {
implicit def optionalDecoder[A](implicit decodeA: Decoder[A]): Decoder[UpdateOptionalField[A]] =
Decoder.withReattempt {
// We're trying to decode a field but it's missing.
case c: FailedCursor if !c.incorrectFocus => Right(None)
case c =>
Decoder.decodeOption[A].tryDecode(c).map {
case Some(a) => Some(UpdateOptionalFieldWith(a))
case None => Some(Delete)
}
}
// Random UUID to _definitely_ avoid collisions
private[this] val marker: String = s"$$marker-${UUID.randomUUID()}-marker$$"
private[this] val markerJson: Json = Json.fromString(marker)
implicit def optionalEncoder[A](implicit encodeA: Encoder[A]): Encoder[UpdateOptionalField[A]] =
Encoder.instance {
case Some(Delete) => Json.Null
case Some(UpdateOptionalFieldWith(a)) => encodeA(a)
case None => markerJson
}
def filterMarkers[A](encoder: Encoder.AsObject[A]): Encoder.AsObject[A] =
encoder.mapJsonObject { obj =>
obj.filter {
case (_, value) => value =!= markerJson
}
}
}

Loss of type info in servlet code

I have a simple flash implementation for use with Jersey that looks like this:
#PostConstruct def before { flash.rotateIn }
#PreDestroy def after { flash.rotateOut }
object flash {
val KeyNow = "local.flash.now"
val KeyNext = "local.flash.next"
// case class Wrapper(wrapped: Map[String, Seq[String]])
case class Wrapper(wrapped: String)
def rotateIn {
for {
session <- Option(request.getSession(false))
obj <- Option(session.getAttribute(KeyNext))
} {
request.setAttribute(KeyNow, obj)
session.removeAttribute(KeyNext)
}
}
def rotateOut {
for (obj <- Option(request.getAttribute(KeyNext))) {
request.getSession.setAttribute(KeyNext, obj)
}
}
def now = Option(request.getAttribute(KeyNow)) match {
case Some(x: Wrapper) => x.wrapped
case Some(x) if x.isInstanceOf[Wrapper] => "WHAT"
case _ => "NOPE"
}
def next(value: String) {
request.setAttribute(KeyNext, Wrapper(value))
}
}
I have simplified it here somewhat, but it lets me set a value for flash with flash.next and read the current flash value with flash.now.
The weird thing is that my now value is always "WHAT". If I do something similar in my REPL, I don't have the same issues:
val req = new org.springframework.mock.web.MockHttpServletRequest
val res = req.getSession
res.setAttribute("foo", Wrapper("foo"))
req.setAttribute("foo", res.getAttribute("foo"))
// Is not None
Option(req.getAttribute("foo")).collect { case x: Wrapper => x }
Am I missing something obvious?
EDIT
I've added a minimal example webapp replicating this issue at https://github.com/kardeiz/sc-issue-20160229.
I tried your example. Check my answer for your other question for details how pattern matching works in this case.
In short, as you Wrapper is an inner class, patter matching also checks the "outer class" reference. It seems that depending on the application server implementation Router.flash can be different instance for each request, so pattern matching fails.
Simple fix for that is to make Wrapper top-level class, so it doesn't have reference to any other class.

Scala: execute anonymous code block for None value in Option

Option class has a good method foreach, which calls passed code if value is specified. Is there any similar techinque for None value? I know about .orElse method, but, using it, I am required to return Option from code block:
x orElse {
// do something
None // <-- I want to avoid this line
}
If you want to do something in the None case I assume you are side-effecting. So what's wrong with:
if(o.isEmpty){
// do things
}
I don't think that it exists in standard Option library, but you can add it with implicit class
class OptionFunctions[T](val opt: Option[T]) extends AnyVal {
def ifEmpty[A](f: => A): Unit = {
if (opt.isEmpty) f
}
}
and use it like this:
val o = Some(1)
o.ifEmpty { println("empty") }
A pattern match perhaps?
option match {
case Some(foo) => println("Have " + foo)
case None => println("Have nothing.")
}

How to implement receive () in Akka Actor

I am in the process of converting Akka UntypedActors in Java code to their Scala equivalent.
However, I am having trouble understanding how to correctly implement the receive() abstract method. The ScalaDoc is a little confusing and most of the examples I see just involve String messages!
My Actor can support multiple message types and this is my solution so far:
override def receive = {
case message if message.isInstanceOf[ClassOne] => {
// do something after message.asInstanceOf[ClassOne]
}
case message if message.isInstanceOf[ClassTwo] => {
// do something after message.asInstanceOf[ClassTwo]
}
case message => unhandled(message)
}
Is there a better way to achieve the above?
override def receive = {
case c: ClassOne =>
// do something after message.asInstanceOf[ClassOne]
case c: ClassTwo =>
// do something after message.asInstanceOf[ClassTwo]
case message => unhandled(message)
}
If you're using case classes, you can get more sophisticated.
case class ClassOne(x: Int, y: String)
case class ClassTwo(a: Int, b: Option[ClassOne])
override def receive = {
case ClassOne(x, y) =>
println(s"Received $x and $y")
case ClassTwo(a, Some(ClassOne(x, y)) if a == 42 =>
// do something
case ClassTwo(a, None) =>
case c # ClassOne(_, "foo") => // only match if y == "foo", now c is your instance of ClassOne
}
All sorts of fun stuff.
receive's type is really just a PartialFunction[Any,Unit], which means you can use Scala's pattern match expressions - in fact, you're already doing it, just not entirely succinctly. A terser equivalent that would also let you handle the type of the match for each case:
def receive = {
case classOneMessage : ClassOne => {
// do something
}
case classTwoMessage : ClassTwo => {
// do something
}
case _ => someCustomLogicHereOtherWiseThereWillBeASilentFailure
//you can, but you don't really need to define this case - in Akka
//the standard way to go if you want to process unknown messages
//within *this* actor, is to override the Actor#unhandled(Any)
//method instead
}
Read the tour article, and the already-linked tutorial for more info on pattern matching, especially in the context of using the feature together with case classes - this pattern is applied regularly when working with Akka, for example here in the Akka manual when handling the ActorIdentity case class.
receive is a regular partial function in Scala. You can write something like this in your case:
case class Example(number: Int, text: String)
override def receive = {
case message: ClassOne =>
// do something with ClassOne instance
case message: ClassTwo =>
// do something with ClassTwo instance
case Example(n, t) =>
println(t * n)
case Example(n, t) if n > 10 =>
println("special case")
}
You don't have to include a special case for unhandled messages unless your application logic requires you to handle all possible messages.
First two cases just match by type of a message and subtypes will be matched as well. Last one not only matches the type Example but also "deconstructs" it using pattern matching.

How to patten match on just the class, not the class attributes in Scala?

I have some classes which sometimes have many many attributes, the classes are very large, so I don't want to turn the class into a case class.
However, I still want to be able to do a pattern match on the class type.
What I have been doing is the following:
object CourseSemester {
implicit val courseSemesterCase = (entity: CourseSemester)
=> { CourseSemesterCase(entity) }
case class CourseSemesterCase(entity: CourseSemester)
}
import CourseSemester._
class CourseSemester(val courses: List[Course],
val startDate: EventDate,
val endDate: EventDate,
val createdUpdatedBy: CreatedUpdatedBy,
... there are so many attributes... ) {
def totalCoursesInSemester: Int = courses.length
}
This allows me to do a match on a CourseSemester to the case class, so I can identify the class type in my pattern match. For example:
val c = new CourseSemester(...)
c match {
case CourseSemesterCase(a) => { }
case SomeOtherCase(b) => { }
}
Is this a reasonable way to do it, or is there a better way?
You may use Type Ascription
c match {
case cs : CourseSemester => // use cs
case s : SomeOther => // s is object of SomeOther type
}