Transform Scala case variable before if guard - scala

I'm using a Scala case statement as follows:
users.collect {
case SomeClass(_, id, _, latestVersion, time)
if latestVersion.getOrElse("null") == someVariable || // etc. =>
// bunch of stuff here
}
latestVariable is an Option and is used frequently inside the if and as part of the code nested inside it.
Is there a way I can transform the Option[String] latest version into a plain String of either "null" or the inner value before going into the if statement? I can't seem to get it to work.

The interpertation of None as "null" string looks a bit disturbing. But otherwise I would usually write an extractor for a situation like this.
object VersionExtractor {
/** I know it looks kinda funny but it does exactly what the op asked for. */
def unnaply(in: Option[String]): Option[String] = in orElse Some("null")
}
You can use it like
case SomeClass(_, id, _, VersionExtractor(latestVersion), time) ...
where latestVersion now is a String that is either "null" or the content of the original Option.
However, in Scala, imho, this could be considered a maltreatment of both the Option and Extractor.
I think a better approach would be to write an extractor for the whole case, somewhere along the lines of
object MyExtractor {
def unapply(input: SomeClass): Option[(<type of id>, String, <type of time>)] = {
input.latestVersion match {
// And now partially in pseudo code:
case Some(version) /* if (input matches some criteria) */ =>
Some((input.id, version, input.time))
case _ =>
None
}
}
}
If done right, your collect should then look like:
users.collect {
case MyExtractor(id, latestVersion /*: String */, time) =>
// bunch of stuff here
}

You can do the test you want more easily by using pattern matching inside your case statement, as follows:
users.collect {
case SomeClass(_, id, _, Some(someVariable), time) =>
// bunch of stuff here
}
This tests that the Option is present and its value is equal to someVariable.

Related

Transform Int to Option[Int]

This is my code:
package net.claritysales.api.helper
import net.claritysales.api.models.UserEntity
import scala.util.Random
trait TestData {
def userInfo(
id : Long = randomLong(),
username : String = randomString(),
password : String = randomString()
) : UserEntity = {
var user : UserEntity = new UserEntity(
id = id, //Error is Long and recived Optional[Long]
username = username,
password = password)
return user}
def randomString(): String = Random.alphanumeric.take(10).mkString("")
def randomLong(): Long = Random.nextLong()
}
and UserEntity:
case class UserEntity(id: Option[Long] = None, username: String, password: String) {
require(!username.isEmpty, "username.empty")
}
and the error message: Type mismatch, expected: Option[Long], actual: Long
How do I transform Optional[Long] to Long ? Id is Optiona[Long] randomLong() and id must is Long. Thanks!
I'm not sure where exactly the issue in your code is, but I'll cover the usual ways to deal with Option. Option solves the same problem that Java's null solves, but it does so in a way that is orders of magnitude better, safer, and easier to work with. So I'm going to work with a hypothetical function here, that just received a Option[A]. The question you need to ask yourself is: what does it mean if I get a None? Scala forces you to ask this question, where making all class types implicitly nullable (as in Java) does not.
Option 1: Propagate the Error Quietly
Perhaps None indicates a failure in the place where we got the A from. Something went wrong, the random generator failed, maybe we divided by zero. Then we want to indicate that we failed. So, in this case, we change our function's return type from A to Option[A] and return a None.
In Java, this would look like this.
if (arg == null)
return null;
return doSomething(arg);
In Scala,
arg map { x => doSomething(x) }
If arg is None, then this returns None. If arg contains a value, it runs doSomething on the value and returns the result, inside an Option[A].
Option 2: None indicates Different Behavior
Perhaps None indicates, in some sense, that we want the function to behave differently. In Java, this would look something like this.
if (arg != null) {
return doSomething(arg);
} else {
return doSomethingElse();
}
In Scala, we do this in a typesafe way.
arg match {
case None => doSomethingElse()
case Some(x) => doSomething(x) // Note that x is A, not Option[A]
}
Option 3: None is Just a Default
Sometimes None just indicates that we want to use a default value. If we're adding up a bunch of numbers, and some of them might be None, we want None to equate to the numerical value 0 so that it doesn't alter our results.
In Java, we might write,
int x = 0;
if (arg != null)
x = arg;
return doSomething(x);
In Scala, we can do this more concisely with getOrElse.
doSomething(arg.getOrElse(0))
Option 4: Propagate the Error Loudly
Maybe None is really bad in our case. Perhaps it's an error in the invoked code that we're just not at all equipped to handle. Perhaps our function is just waaaay too important, and if it fails then everything else is forfeit. Then we can raise an exception. Note that this approach is not very idiomatic in Scala, so it should be used very sparingly, only when it doesn't make sense to do any of the above.
In Java,
if (arg == null)
throw new RuntimeException("Oops!");
return doSomething(arg);
In Scala,
arg match {
case None => sys.error("Oops!")
case x => doSomething(x)
}
The problem isn't that you have an Option[Int] and need an Int (as you've claimed in the title and body of your question). It's that you have an Int and need an Option[Int]. This is because userInfo takes an Int, but UserEntity takes an Option[Int].
To solve this problem, you can simply pass Some(id) as the argument.
Use get or else, i dont know in your case what give in None case
var user : UserEntity = new UserEntity(
id = id.getOrElse(0l)
username = username,
password = password)
return user}

Capture argument to partial function

I am trying to debug a Scala program (this is a build.sbt, but the question is not particular for sbt), where I need to give a partial function for a certain sbt setting. The value for the partial function looks like this
{
case Regex1(a,b,c) =>
case Regex2(d,e,f) =>
...
}
The partial function does not do what I want, so I wanted to debug it. Because I don't know exactly what is passed in, I want to capture the value that is passed into the partial function, but I don't know how to do that.
I could add a case a => println(a) at the beginning of the partial function, but this breaks the whole function.
You can do this:
val print: PartialFunction[InputType, InputType] = { case i => println(i); i }
print andThen {
case Regex1(a,b,c) => ...
case ...
}
I finally figured out how to do it. It is not very elegant, so if anyone knows of a better way, please add another answer!
The solution is to create the partial function explicitly as value:
val result = new PartialFunction[InputType,ResultType] {
def apply(value: InputType) = {
println("input is: " + value) // Yay, I captured the value
value match {
// Same as above
}
}
def isDefinedAt(value: InputType) = true
}
result
Another option would be to match all, and add another match that does the actual work:
{
case value => {
println(value)
value match {
// the original partial function
...
// you might need to add a catch-all that
// does nothing or returns a default value
case _ => None
}
}
}

Using Option with cleaner code

Apologies if this is a newbie question...
In Scala I understand that it is preferred to use an Option rather than returning null when you have a function which returns an instance but could potentially return nothing. I understand that this makes it better with regards to safety, because you are not passing null references around, and risking NullPointerException somewhere down the line.
However, is there a cleaner way to handle options than using pattern matching?
The syntax I end up using is the following:
val optObj : Option[MyObject] = myFunctionThatReturnsOption
optObj match {
case Some(obj) => {
//my code using obj
}
case None => _
}
In reality all this doing is the equivalent of the Java version:
MyObject obj = myMethodThatCanReturnNull()
if (obj != null) {
//my code using obj
}
Is there some other way to avoid all this boilerplate in Scala when using Option instead of null references? All I want to do is execute a piece of code as long as the Option contains some object (i.e. is not None).
Use foreach, getOrElse and/or map if you want to work in a more consistent way. Here's some use cases and what I'd do:
//I want to get a non-null value and I have a sane default
val result = myOption getOrElse 3
//I want to perform some side effecting action but only if not None
myOption foreach{ value =>
println(value toString ())
}
//equivalently
for(value <- myOption){
//notice I haven't used the "yeild" keyword here
}
//I want to do a computation and I don't mind if it comes back as an Option
val result = for(value <- myOption) yield func(value)
val equivalent = myOption map func
The third example will use map in both cases.
It gets really interesting when you can mix and match things in a "for comprehension" (Google term.) Let's say that func also returns an Option but I only want things working in specific cases:
val result = for{
value <- myOption if value > 0
output <- func(value)
} yield output
Now I get back an Option but only if myOption contained an integer that was greater than zero. Pretty nifty stuff, no?
You can use foreach if you just want to perform some side-effecting operation with the value:
optObj.foreach(obj => {
//my code using obj
})
if you have some other use case you should use some other method on Option like map, filter or getOrElse.
Of course, the way I usually use options if I only care about present value is foreach:
optObj.foreach { obj =>
//...
}
Having said this, there are a lot of other options (which #wheaties enlisted) and some people keep battling about the true one.
You can use the flatMap-method pretty well with Option. Like hier:
case class Player(name: String)
def lookupPlayer(id: Int): Option[Player] = {
if (id == 1) Some(new Player("Sean"))
else if(id == 2) Some(new Player("Greg"))
else None
}
def lookupScore(player: Player): Option[Int] = {
if (player.name == "Sean") Some(1000000) else None
}
println(lookupPlayer(1).map(lookupScore)) // Some(Some(1000000))
println(lookupPlayer(2).map(lookupScore)) // Some(None)
println(lookupPlayer(3).map(lookupScore)) // None
println(lookupPlayer(1).flatMap(lookupScore)) // Some(1000000)
println(lookupPlayer(2).flatMap(lookupScore)) // None
println(lookupPlayer(3).flatMap(lookupScore)) // None
Here's a great reference for Scala best practices regarding options:
http://blog.tmorris.net/posts/scalaoption-cheat-sheet/index.html

How to handle Option of List in Scala?

Suppose I have a function getCustomers and getOrdersByCustomer.
def getCustomer():List[Customer] = ...
def getOrdersByCustomer(cust: Customer): List[Order] = ...
Now I can easily define a function getOrdersOfAllCustomers
def getOrdersOfAllCustomers(): List[Order] =
for(cust <- getCustomer(); order <- getOrderByCustomer(cust)) yield order
So far, so good but what if getCustomer and getOrdersByCustomer return Options of the lists ?
def getCustomer():Option[List[Customer]] = ...
def getOrdersByCustomer(cust: Customer): Option[List[Order]] = ...
Now I would like to implement two different flavors of getOrdersOfAllCustomers():
Return None if one of the functions returns None;
Return None if getCustomer returns None and do not care if getOrdersByCustomer returns None.
How would you suggest implement it?
I think you should consider three possibilities--a populated list, an empty list, or an error--and avoid a lot of inelegant testing to figure out which one happened.
So use Try with List:
def getOrdersOfAllCustomers(): Try[List[Order]] = {
Try(funtionReturningListOfOrders())
}
If all goes well, you will come out with a Success[List[Order]]; if not, Failure[List[Order]].
The beauty of this approach is no matter which happens--a populated list, an empty list, or an error--you can do all the stuff you want with lists. This is because Try is a monad just like Option is. Go ahead and filter, forEach, map, etc. to your heart's content without caring which of those three occurred.
The one thing is that awkward moment when you do have to figure out if success or failure happened. Then use a match expression:
getOrdersOfAllCustomers() match {
case Success(orders) => println(s"Awww...yeah!")
case Failure(ex) => println(s"Stupid Scala")
}
Even if you don't go with the Try, I implore you not to treat empty lists different from populated lists.
Try this,
def getOrdersOfAllCustomers(): Option[List[Order]] =
for{
cust <- getCustomer().toList.flatten;
order <- getOrderByCustomer(cust).toList.flatten
} yield order
This should do it:
def getOrdersOfAllCustomers(): Option[List[Order]] = {
getCustomer() flatMap { customers =>
//optOrders is a List[Option[List[Order]]]
val optOrders = customers map { getOrderByCustomer }
// Any result must be wrapped in an Option because we're flatMapping
// the return from the initial getCustomer call
if(optOrders contains None) None
else {
// map the nested Option[List[Order]]] into List[List[Order]]
// and flatten into a List[Order]
// This then gives a List[List[Order]] which can be flattened again
Some(optOrders.map(_.toList.flatten).flatten)
}
}
}
The hard part is handling the case where one of the nested invocations of getOrderByCustomer returns None and bubbling that result back to the outer scope (which is why using empty lists is so much easier)

Can extractors be customized with parameters in the body of a case statement (or anywhere else that an extractor would be used)?

Basically, I would like to be able to build a custom extractor without having to store it in a variable prior to using it.
This isn't a real example of how I would use it, it would more likely be used in the case of a regular expression or some other string pattern like construct, but hopefully it explains what I'm looking for:
def someExtractorBuilder(arg:Boolean) = new {
def unapply(s:String):Option[String] = if(arg) Some(s) else None
}
//I would like to be able to use something like this
val {someExtractorBuilder(true)}(result) = "test"
"test" match {case {someExtractorBuilder(true)}(result) => result }
//instead I would have to do this:
val customExtractor = someExtractorBuilder(true)
val customExtractor(result) = "test"
"test" match {case customExtractor(result) => result}
When just doing a single custom extractor it doesn't make much difference, but if you were building a large list of extractors for a case statement, it could make things more difficult to read by separating all of the extractors from their usage.
I expect that the answer is no you can't do this, but I thought I'd ask around first :D
Parameterising extractors would be cool, but we don't have the resources to implement them right now.
Nope.
8.1.7 Extractor Patterns
An extractor pattern x (p 1 , . . . ,
p n ) where n ≥ 0 is of the same
syntactic form as a constructor
pattern. However, instead of a case
class, the stable identifier x denotes
an object which has a member method
named unapply or unapplySeq that
matches the pattern.
One can customize extractors to certain extent using implicit parameters, like this:
object SomeExtractorBuilder {
def unapply(s: String)(implicit arg: Boolean): Option[String] = if (arg) Some(s) else None
}
implicit val arg: Boolean = true
"x" match {
case SomeExtractorBuilder(result) =>
result
}
Unfortunately this cannot be used when you want to use different variants in one match, as all case statements are in the same scope. Still, it can be useful sometimes.
Late but there is a scalac plugin in one of my lib providing syntax ~(extractorWith(param), bindings):
x match {
case ~(parametrizedExtractor(param)) =>
"no binding"
case ~(parametrizedExtractor(param), (a, b)) =>
s"extracted bindings: $a, $b"
}
https://github.com/cchantep/acolyte/blob/master/scalac-plugin/readme.md
Though what you are asking isn't directly possible,
it is possible to create an extractor returning a contaner that gets evaluated value in the if-part of the case evaluation. In the if part it is possible to provide parameters.
object DateExtractor {
def unapply(in: String): Option[DateExtractor] = Some(new DateExtractor(in));
}
class DateExtractor(input:String){
var value:LocalDate=null;
def apply():LocalDate = value;
def apply(format: String):Boolean={
val formater=DateTimeFormatter.ofPattern(format);
try{
val parsed=formater.parse(input, TemporalQueries.localDate());
value=parsed
true;
} catch {
case e:Throwable=>{
false
}
}
}
}
Usage:
object DateExtractorUsage{
def main(args: Array[String]): Unit = {
"2009-12-31" match {
case DateExtractor(ext) if(ext("dd-MM-yyyy"))=>{
println("Found dd-MM-yyyy date:"+ext())
}
case DateExtractor(ext) if(ext("yyyy-MM-dd"))=>{
println("Found yyyy-MM-dd date:"+ext())
}
case _=>{
println("Unable to parse date")
}
}
}
}
This pattern preserves the PartialFunction nature of the piece of code. I find this useful since I am quite a fan of the collect/collectFirst methods, which take a partial function as a parameter and typically does not leave room for precreating a set of extractors.