dazito dazito - 3 months ago 12
Scala Question

`getOrElse` to stop process or return different class type

Let's say I've this code:

val parsedMessage: JsResult[Message] = Json.fromJson(Json.parse(msg))

val message: Message = parsedMessage.getOrElse {
log.warning("Invalid json: {}", msg)
RejectedMessageEvent(msg)
}

val newMessageEvent: NewMessageEvent = NewMessageEvent (userId, message.to, message.text)

messagePersistentActor ! message


Obviously this fails at compile time because the
getOrElse
doesn't return an object of type
Message
. But let's say, for some reason, the
parsedMessage
fails and I get inside the 'else' part of
getOrElse
. Here I want to either stop the process (in Java it would be a
return
) or return a
RejectedMessageEvent
- which gives a compile error as expected.

As a typical Java developer, I'm keen to use:

if(parsedMessage.isError) {
log.warning("Invalid json: {}", msg)
messagePersistentActor ! RejectedMessageEvent(msg)
}
else {
val newMessageEvent: NewMessageEvent = NewMessageEvent (userId, message.to, message.text, UUID.randomUUID().toString, DateTime.now.getMillis)
messagePersistentActor ! message
}


But I feel this is not the best practice for Scala.

How would you solve this case where I either want to stop the process inside the
getOrElse
, or return a different object type than the declared one for that variable?

I know I could omit the Message type declaration at
val message: Message = parsedMessage.getOrElse
and make it simply
val message = parsedMessage.getOrElse
, but then I would not be able to do
message.to
and
message.text
on the
NewMessageEvent
case class constructor because
message
could either be type of
Message
or
RejectedMessageEvent
.

I'm using case classes and I could use the inheritance (
RejectedMessageEvent
and
NewMessageEvent
both extending
Message
), but I'm trying to avoid this solution and go for a more practical one.

Answer

It is very common in scala to replace if (someOptValue.isDefined) ... else ... with this pattern someOptValue.map(value => ...).getOrElse(...):

messagePersistentActor ! parsedMessage.map {msg =>
  NewMessageEvent (userId, msg.to, msg.text)
}.getOrElse {
  log.warning("Invalid json: {}", msg)
  RejectedMessageEvent(msg)
}
Comments