Is there any efficient way to remove the below if and else condition
object Currency {
sealed trait MyConstants extends MyTrait[String]
case object A extends MyConstants {val value ="abc"}
case object B extends MyConstants {val value = "def"}
}
case class Test(name:String)
case class MyCurerncy(currency: Option[MyConstants])
def check (name:String):Option[Test] ={.....}
if(check("xyz").isDefined){
MyCurerncy(Option(Currency.A))
}else{
None
}
The method check return the Option[Test] .I need to populate MyCurrency based on the condition if Test is defined or not.
MyCurerncy(Option(Currency.A)) is of type MyCurerncy.
None is of type Option[Nothing].
So
if(check("xyz").isDefined){
MyCurerncy(Option(Currency.A))
}else{
None
}
will be of type Any (actually Product with Serializable but it doesn't matter). Are you sure you prefer to have Any?
If you prefer to have MyCurerncy i.e.
if(check("xyz").isDefined){
MyCurerncy(Option(Currency.A))
}else{
MyCurerncy(None)
}
you can write
MyCurerncy(check("xyz").flatMap(_ => Option(Currency.A)))
If you anyway prefer Any you can write as you wrote or match
check("xyz") match {
case Some(_) => MyCurerncy(Option(Currency.A))
case None => None
}
Related
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>
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
}
}
}
I am wondering what is the idiomatic way to express similar messages (value objects)
Let's say I have some messages that I want to send : UserEnter, UserLeft, UserSendGreeting etc'. I hope that the following can express my dilemma
there are two options that I think one can express it :
trait UserAction
case class UserEnter (username:String,hour:Long,day:WeekDay,room:Int)
case class UserLeft (username:String,hour:Long,day:WeekDay,room:Int)
case class UserSendGreeting (username:String,,hour:Long,day:WeekDay,greeting:String)
def foo(userActions:List[UserAction]) = {
userActions match {
case UserEnter(userName)::tail =>
sendWelcomeMessage(userName)
handleOtherActions(tail)
case UserLeft::tail => "must enter first"
case _ => "do something else"
}
another way is :
trait Action
case class Enter(room:Int) extends Action
case object Left(room:Int) extends Action
case object Greet(msg:String) extends Action
case class UserAction(username:String,action:Action,,hour:Long,day:WeekDay)
def foo(userActions:List[UserAction]) = {
userActions match {
case head::tail if head.action == Enter =>
sendWelcomeMessage(head.userName)
handleOtherActions(tail)
case head::tail if head.action == Left => "must enter first"
case _ => "do something else"
}
The 1st option is more explicit and easier to pattern match but more repetitive code.
The other one is more explicit on the action itself but pattern match is more verbose
which way is better ?
Don't overcomplicate things. If you need to have a pair of User (in your case string name) and Action, use Tuple. Also it makes sense to gather all "...other attributes" inside corresponding Action.
type User = String
sealed trait Action
case class Enter(room:Int) extends Action
case class Left(room:Int) extends Action
case class Greet(msg:String) extends Action
def foo(userActions:List[(User, Action)]) = userActions match {
case (username, _:Enter)::tail =>
sendWelcomeMessage(username)
handleOtherActions(tail)
case (username, _:Left)::tail => "must enter first"
case _ => "do something else"
}
Also don't forget, that pattern matching allows you to unapply hierarchies of arbitrary depth:
case (username, Enter(room))::tail =>
I think the 1 way is better but you can make a constraint on UserAction trait to have username field:
trait UserAction {
def username: String
}
case class UserEnter(username:String, room:Int)
case class UserLeft(username:String, room:Int)
case class UserSendGreeting(username:String, greeting:String)
This way it is easy to
1) pattern match
2) use generic UserAction to get username field
How about: case class UserAction(user: User, action: Action)
def foo(actions: Seq[UserActions]) = actions match {
case UserAction(user, _: EnterAction)::tail =>
processEnter(user)
handleOtherActions(tail)
case UserExit(user, _: ExitAction)::tail => processExit(user)
...
}
Or even better
def foo(actions: Seq[UserAction]) = actions.find { ua =>
!ua.action.process(ua.user)
}
Or, maybe, just
def foo(action: Seq[UserAction]) = actions.find { !_.process }
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
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
}