Is it possible to 'automatically'/implicitly enrich an anonymous function? - scala

Given:
enum Car { Mustang, Camaro, Challenger }
enum Driver { Bob, John, Mike }
trait Config {
def car:Car
def driver:Driver
def collect[O](f:PartialFunction[(Car,Driver),O]):O
}
def canDrive(config:Config):Boolean = config collect {
//what should 'collect' accept in order to satisfy the following:
// (1) maintain the terseness
// (2) always have access to values of Car and Driver enums
case (Mustang, Bob) => false
case (Camaro, Mike) => false
case _ => true
}
I suppose all enum values can be tucked away into a separate trait:
trait AllEnumValues {
val (Mustang, Camaro, Challenger) = (Car.Mustang, Car.Camaro, Challenger)
val (Bob, John, Mike) = (Driver.Bob, Driver.John, Driver.Mike)
}
But, how would I enrich the arg to Config.collect such that when the anonymous partial function is created I have access to everything inside of AllEnumValues without an implicit import statement

Related

Scala pattern matching type with inherited classes

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>

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
}
}
}

scala nested for comprehension with futures

My case domain classes are as below
case class Account(randomId: String, accounts: List[String]) // for each of accounts i need to get AccountProfiles.
case class AccountProfiles(actId: String, profiles: List[String], additionalInfo: Map[String, String], ......)
case class AccountInfo(id: String, profiles:List[String]) // for each of AccountProfiles I need to construct AccountInfo
my access layer implementation signature to extract above domain classes look like below
getLinked(): Future[Account]
getAccountProfile(actId: String): Future[AccountProfiles]
Can I have a for comprehension to construct Future list of AccountInfo domain object with the help of getLinked and getAccountProfile methods ?
Yes you can. I think this is what you're looking for assuming AccountProfiles.actId and AccountInfo.id are supposed to be equivalent.
for {
account <- getLinked()
profiles <- Future.sequence(account.accounts map { id => getAccountProfile(id) })
} yield profiles map { p => AccountInfo(p.actId, p.profiles) }

Scala Reflection to update a case class val

I'm using scala and slick here, and I have a baserepository which is responsible for doing the basic crud of my classes.
For a design decision, we do have updatedTime and createdTime columns all handled by the application, and not by triggers in database. Both of this fields are joda DataTime instances.
Those fields are defined in two traits called HasUpdatedAt, and HasCreatedAt, for the tables
trait HasCreatedAt {
val createdAt: Option[DateTime]
}
case class User(name:String,createdAt:Option[DateTime] = None) extends HasCreatedAt
I would like to know how can I use reflection to call the user copy method, to update the createdAt value during the database insertion method.
Edit after #vptron and #kevin-wright comments
I have a repo like this
trait BaseRepo[ID, R] {
def insert(r: R)(implicit session: Session): ID
}
I want to implement the insert just once, and there I want to createdAt to be updated, that's why I'm not using the copy method, otherwise I need to implement it everywhere I use the createdAt column.
This question was answered here to help other with this kind of problem.
I end up using this code to execute the copy method of my case classes using scala reflection.
import reflect._
import scala.reflect.runtime.universe._
import scala.reflect.runtime._
class Empty
val mirror = universe.runtimeMirror(getClass.getClassLoader)
// paramName is the parameter that I want to replacte the value
// paramValue is the new parameter value
def updateParam[R : ClassTag](r: R, paramName: String, paramValue: Any): R = {
val instanceMirror = mirror.reflect(r)
val decl = instanceMirror.symbol.asType.toType
val members = decl.members.map(method => transformMethod(method, paramName, paramValue, instanceMirror)).filter {
case _: Empty => false
case _ => true
}.toArray.reverse
val copyMethod = decl.declaration(newTermName("copy")).asMethod
val copyMethodInstance = instanceMirror.reflectMethod(copyMethod)
copyMethodInstance(members: _*).asInstanceOf[R]
}
def transformMethod(method: Symbol, paramName: String, paramValue: Any, instanceMirror: InstanceMirror) = {
val term = method.asTerm
if (term.isAccessor) {
if (term.name.toString == paramName) {
paramValue
} else instanceMirror.reflectField(term).get
} else new Empty
}
With this I can execute the copy method of my case classes, replacing a determined field value.
As comments have said, don't change a val using reflection. Would you that with a java final variable? It makes your code do really unexpected things. If you need to change the value of a val, don't use a val, use a var.
trait HasCreatedAt {
var createdAt: Option[DateTime] = None
}
case class User(name:String) extends HasCreatedAt
Although having a var in a case class may bring some unexpected behavior e.g. copy would not work as expected. This may lead to preferring not using a case class for this.
Another approach would be to make the insert method return an updated copy of the case class, e.g.:
trait HasCreatedAt {
val createdAt: Option[DateTime]
def withCreatedAt(dt:DateTime):this.type
}
case class User(name:String,createdAt:Option[DateTime] = None) extends HasCreatedAt {
def withCreatedAt(dt:DateTime) = this.copy(createdAt = Some(dt))
}
trait BaseRepo[ID, R <: HasCreatedAt] {
def insert(r: R)(implicit session: Session): (ID, R) = {
val id = ???//insert into db
(id, r.withCreatedAt(??? /*now*/))
}
}
EDIT:
Since I didn't answer your original question and you may know what you are doing I am adding a way to do this.
import scala.reflect.runtime.universe._
val user = User("aaa", None)
val m = runtimeMirror(getClass.getClassLoader)
val im = m.reflect(user)
val decl = im.symbol.asType.toType.declaration("createdAt":TermName).asTerm
val fm = im.reflectField(decl)
fm.set(??? /*now*/)
But again, please don't do this. Read this stackoveflow answer to get some insight into what it can cause (vals map to final fields).

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
}