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}
Related
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.
I have the below code and in my findOrCreate() function, I'm getting an error saying Type mismatch found Unit, required Future[Customer]. The customerByPhone() function that is being called inside findOrCreate() also contains calls that are expecting Futures, which is why I'm using a fatmap. I don't know why the result of the flatmap is resulting in Unit. What am I doing wrong?
override def findOrCreate(phoneNumber: String, creationReason: String): Future[AvroCustomer] = {
//query for customer in db
val avroCustomer: Future[AvroCustomer] = customerByPhone(phoneNumber).flatMap(_ => createUserAndEvent(phoneNumber, creationReason, 1.0))
}
override def customerByPhone(phoneNumber: String): Future[AvroCustomer] = {
val query = Schema.Customers.byPhoneNumber(phoneNumber)
val dbAction: DBIO[Option[Schema.Customer]] = query.result.headOption
db.run(dbAction)
.map(_.map(AvroConverters.toAvroCustomer).orNull)
}
private def createUserAndEvent(phoneNumber: String, creationReason: String, version: Double): Future[AvroCustomer] = {
val query = Schema.Customers.byPhoneNumber(phoneNumber)
val dbAction: DBIO[Option[Schema.Customer]] = query.result.headOption
val data: JsValue = Json.obj(
"phone_number" -> phoneNumber,
"agent_number" -> "placeholder for agent number",
"creation_reason" -> creationReason
)
//empty for now
val metadata: JsValue = Json.obj()
//creates user
val avroCustomer: Future[AvroCustomer] = db.run(dbAction).map(_.map(AvroConverters.toAvroCustomer).orNull)
avroCustomer.onComplete({
case Success(null) => {
}
//creates event
case Success(customer) => {
val uuid: UUID = UUID.fromString(customer.id)
//create event
val event: Future[CustomerEvent] = db.run(Schema.CustomerEvents.create(
uuid,
"customer_creation",
version,
data,
metadata)
).map(AvroConverters.toAvroEvent)
}
case Failure(exception) => {
}
})
Future.successful(new AvroCustomer)
}
While Reactormonk basically answered this in the comments, I'm going to actually write an answer with some details. His comment that a val statement produces Unit is fundamentally correct, but I'm hoping some elaboration will make things more clear.
The key element that I see is that val is a declaration. Declarations in Scala are statements that don't produce useful values. Because of the functional nature of Scala, they do produce a value, but it is Unit and as there is only one instance of Unit, it doesn't carry any meaning.
The reason programmers new to Scala are often tempted to do something like this is that they don't think of blocks of code as statements and are often used to using return in other languages. So let's consider a simplified function here.
def foo(i: Int): Int = {
42 * i
}
I include a code block as I think that is key to this error, though it really isn't needed here. The value of a code block is simply the value of the last expression in the code block. This is why we don't have to specify return, but most programmers who are used to return are a bit uncomfortable with that naked expression at the end of a block. That is why it is tempting to throw in the val declaration.
def foo(i: Int): Int = {
val result = 42 * i // Error: type mismatch.
}
Of course, as was mentioned, but val results in Unit making this incorrect. You could add an extra line with just result, and that will compile, but it is overly verbose and non-idiomatic.
Scala supports the use of return to leave a method/function and give back a particular value, though the us is generally frowned upon. As such, the following code works.
def foo(i: Int): Int = {
return 42 * i
}
While you shouldn't use return in Scala code, I feel that imagining it being there can help with understanding what is wrong here. If you stick a return in front of the val you get code like the following.
def foo(i: Int): Int = {
return val result = 42 * i // Error: type mismatch.
}
At least to me, this code is clearly incorrect. The val is a declaration and as such it just doesn't work with a return. It takes some time to get used to the functional style of blocks as expressions. Until you get to that point, it might help just to act like there is a return at the end of methods without actually putting one there.
It is worth noting that, in the comments, jwvh claims that a declaration like this in C would return a value. That is false. Assignments in most C-family languages give back the value that was assigned, so a = 5 returns the value 5, but declarations don't, so int a = 5; does not give back anything and can't be used as an expression.
case class Account(
val name: String,
val uuid: String,
val lat: Double,
val lng: Double
)
}
object Account {
def create(row: Row): Option[YellowAccount] = {
val name = row.getAs[String]("store_name")
val uuid = row.getAs[String]("uuid")
val latO = row.getAs[String]("latitude")
val lngO = row.getAs[String]("longitude")
// How do you do null checks here in an idiomatic way?
if (latO == null || lngO == null) {
return None
}
Some(YellowAccount(name, uuid, latO.toDouble, lngO.toDouble))
}
}
lat/long are compulsory fields in Account. How do you do null checks in an idiomatic way?
You can use Option type to handle null values. You just wrap a nullable value in Option and then you can pattern match on it or something else. In your example, I think the most concise way to combine 4 nullable values is for-comprehension:
import scala.util.Try
object Account {
def create(row: Row): Option[YellowAccount] = {
for {
name <- Option( row.getAs[String]("store_name") )
uuid <- Option( row.getAs[String]("uuid") )
latO <- Try( row.getAs[String]("latitude").toDouble ).toOption
lngO <- Try( row.getAs[String]("longitude").toDouble ).toOption
} yield
YellowAccount(name, uuid, latO, lngO)
}
}
EDIT
Another thing here is _.toDouble conversion, which may throw an exception if it fails to parse the string, so you can wrap it in Try instead (I updated the code above).
EDIT2
To clarify what's happening here:
when you wrap a value in Option it becomes None if the value is null, or Some(...) with the value otherwise
similarly when wrapping something that may throw an exception in Try, it becomes either Failure with the exception, or Success with the value
toOption method converts Try to Option in a straightforward way: Failure becomes None, Success becomes Some
in the for-comprehension if any of the four Options returns None (i.e. one of them was null of failed to parse a number), the whole statement returns None, and only if each of the four yields a value, they are passed to the YellowAccount constructor
As the other answer suggests, you can use Option to handle possible nulls. You can't use for comprehension the way it is suggested there, but there are several ways around it. The easiest, probably is to .zip the two Options together, and then map over the result:
Option(row.getAs[latitude])
.zip(Option(row.getAs[String]("longitude")))
.map { case (lat, long) =>
YellowAccount(
row.getAs[String]("store_name"),
row.getAs[String]("uuid"),
lat.toDouble,
long.toDouble
)
}
Here is an idiom I find myself writing.
def chooseName(nameFinder: NameFinder) = {
if(nameFinder.getReliableName.isEmpty) nameFinder.getReliableName
else nameFinder.secondBestChoice
}
In order to avoid calling getReliableName() twice on nameFinder, I add code that makes my method look less elegant.
def chooseName(nameFinder: NameFinder) = {
val reliableName = nameFinder.getReliableName()
val secondBestChoice = nameFinder.getSecondBestChoice()
if(reliableName.isEmpty) reliableName
else secondBestChoice
}
This feels dirty because I am creating an unnecessary amount of state using the vals for no reason other than to prevent a duplicate method call. Scala has taught me that whenever I feel dirty there is almost always a better way.
Is there a more elegant way to write this?
Here's two Strings, return whichever isn't empty while favoring the first
There's no need to always call getSecondBestChoice, of course. Personally, I find nothing inelegant about the code after changing that - it's clear what it does, has no mutable state. The other answers just seem overcomplicated just to avoid using a val
def chooseName(nameFinder: NameFinder) = {
val reliableName = nameFinder.getReliableName()
if(reliableName.isEmpty) reliableName
else nameFinder.getSecondBestChoice()
}
If you really want to avoid the val, here's another variant (generalises well if there are more than two alternatives)
List(nameFinder.getReliableName(), nameFinder.getSecondBestChoice()).find(_.nonEmpty).get
(or getOrElse(lastResort) if everything in the list may be empty too)
Here's a way using Option. It's not that much prettier, but everything is called only once. This assumes you want a String as a result, and don't care if the second string is empty.
Some(nameFinder.getReliableName)
.filter(_.nonEmpty)
.getOrElse(nameFinder.secondBestChoice)
Option(namefinder.getReliableName) // transforms a potential null into None
.filter(_.trim.nonEmpty) // "" is None, but also " "
.getOrElse(nameFinder.secondBestChoice)
Or better, if you can modify getReliableName to return an Option[String]:
def chooseName(nameFinder: NameFinder): String =
namefinder.getReliableName getOrElse nameFinder.secondBestChoice
Finally, if secondBestChoice can fail as well (assuming it returns an Option[String]):
def chooseName(nameFinder: NameFinder): Option[String] =
namefinder.getReliableName orElse nameFinder.secondBestChoice
If you need it more than once:
scala> implicit class `nonempty or else`(val s: String) extends AnyVal {
| def nonEmptyOrElse(other: => String) = if (s.isEmpty) other else s }
defined class nonempty
scala> "abc" nonEmptyOrElse "def"
res2: String = abc
scala> "" nonEmptyOrElse "def"
res3: String = def
Using the following pattern matching may deliver a neater scalish code,
def chooseName(nameFinder: NameFinder) = {
nameFinder.getReliableName match {
case r if r.isEmpty => r
case _ => nameFinder.secondBestChoice
}
}
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