I working with play for Scala (2.1) and I need to convert an Option[Long] value to Long.
I know how to do the opposite, I mean:
def toOption[Long](value: Long): Option[Long] = if (value == null) None else Some(value)
But in my case, I have to pass a value of Option[Long] as a type into a method that takes Long.
If you have x as Option[Long], x.get will give you Long.
First of all, your implementation of "the opposite" has some serious problems. By putting a type parameter named Long on the method you're shadowing the Long type from the standard library. You probably mean the following instead:
def toOption(value: Long): Option[Long] =
if (value == null) None else Some(value)
Even this is kind of nonsensical (since scala.Long is not a reference type and can never be null), unless you're referring to java.lang.Long, which is a recipe for pain and confusion. Finally, even if you were dealing with a reference type (like String), you'd be better off writing the following, which is exactly equivalent:
def toOption(value: String): Option[String] = Option(value)
This method will return None if and only if value is null.
To address your question, suppose we have the following method:
def foo(x: Long) = x * 2
You shouldn't generally think in terms of passing an Option[Long] to foo, but rather of "lifting" foo into the Option via map:
scala> val x: Option[Long] = Some(100L)
x: Option[Long] = Some(100)
scala> x map foo
res14: Option[Long] = Some(200)
The whole point of Option is to model (at the type level) the possibility of a "null" value in order to avoid a whole class of NullPointerException-y problems. Using map on the Option allows you to perform computations on the value that may be in the Option while continuing to model the possibility that it's empty.
As another answer notes, it's also possible to use getOrElse to "bail out" of the Option, but this usually isn't the idiomatic approach in Scala (except in cases where there really is a reasonable default value).
This method is already defined on Option[A] and is called get :
scala> val x = Some(99L)
x: Some[Long] = Some(99)
scala> x.get
res0: Long = 99
The problem is that calling get on None will throw a NoSucheElement Exception:
scala> None.get
java.util.NoSuchElementException: None.get
thus you will not gain any benefits from using an Option type.
Thus as stated before you can use getOrElse if you can provide a sensible default value or handle the Exception.
The idiomatic scala way would be using map or a for-comprehension
x map (_ + 1)
res2: Option[Long] = Some(100)
or
for (i <- x) yield i +1
res3: Option[Long] = Some(100)
Option is way to localise side-effect (your function can return empty value). And good style to lift your computation to Option (Option is Monad with map & flatMap methods).
val x = Option[Long](10)
x.map { a => a + 10 }
And extract value with manually processing of side effect:
val res = x match {
case Some(a) => s"Value: $a"
case None => "no value"
}
You need to decide what happens when the option is None. Do you provide a default value?
def unroll(opt: Option[Long]): Long = opt getOrElse -1L // -1 if undefined
unroll(None) // -> -1
You could also throw an exception:
def unroll(opt: Option[Long]): Long = opt.getOrElse(throw
new IllegalArgumentException("The option is expected to be defined at this point")
)
unroll(None) // -> exception
In case, refrain from using null, unless you have very good reasons to use it (opt.orNull).
As has already been mentioned getOrElse is probably what you're looking for in answering your question directly.
Please note also that to convert to an option you can simply:
val myOption = Option(1)
myOption will now be Some(1)
val myOption = Option(null)
myOption will now be None.
Related
i'm getting an error when trying to getOrElse 2 values. As a stripped down example, all i'm trying to do is:
take a string value
check if its a range (eg 50-60). if it is, take the first value before the '-', else take the whole value
return the value as an Option[Double] for further processing
def deriveResult(inputValue: Option[String]): String = {
val hyphenIndex = inputValue.get.indexOf("-")
// parse the low range
val rangedValue: Option[java.lang.Double] = if (hyphenIndex != -1) {
val lowRangeStringUntruncated = inputValue.get.substring (0, hyphenIndex)
val lowRangeString = lowRangeStringUntruncated.substring (0, scala.math.min (lowRangeStringUntruncated.length, 8) )
scala.util.Try[java.lang.Double](lowRangeString.toDouble).toOption
} else null
val nonRangedValue: Option[java.lang.Double] = scala.util.Try[java.lang.Double](inputValue.get.toDouble).toOption
val valueOptDouble: Option[java.lang.Double] = Option(rangedValue.getOrElse(nonRangedValue))
...
<do something with valueOptDouble>
}
Error:(157, 89) type mismatch;
found : Option[Double]
required: Double
val valueOptDouble: Option[java.lang.Double] = Option(rangedValue.getOrElse(nonRangedValue))
I'm sure this could be written much more concisely, but what i'm confused about is why the final line results in this error, as it seems both rangedValue and nonRangedValue are of type Option[Double]
Thanks for any help
The type error is with
rangedValue.getOrElse(nonRangedValue)
because getOrElse here expects Double argument but nonRangedValue is Option[Double]. Perhaps try orElse instead of getOrElse
val valueOptDouble: Option[Double] = rangedValue orElse nonRangedValue
You probably want to take a look at the Scaladoc to learn about useful combinators like map and flatMap
I really, couldn't understand what your code does, so here is an attempt to solve the same problem.
In any case, I believe the code should be easy to adapt to your real needs, but feel free to ask any questions or provide clarification over the problem so I could edit the code.
def getValueFromString(inputValue: String): Option[Double] =
inputValue.split('-').toList match {
case raw1 :: raw2 :: Nil =>
for {
first <- raw1.toDoubleOption
second <- raw2.toDoubleOption
} yield if (first < 60.0d) first else second
case _ =>
None
And then you can pass this method to a flatMap of the original Option[String] like this:
Some("10-30").flatMap(getValueFromString)
// res: Option[Double] = Some(10.0d)
You can see the code running here.
Just do inputValue.split("-").head.toDouble
I have 2 options, and I need to take average of the values they hold.
It is possible that one or both may be missing. If one of the value is missing, I would just take other one as the average. But if both are missing, I would resort to some default value.
How can this be done in a clean way?
I can check absence of value using isEmpty, but then won't that would be same as null check?
I guess this is self-explanatory:
val option1 = Some(12.0)
val option2 = None
val default = 0.0
val average = (option1, option2) match {
case (Some(val1), Some(val2)) => (val1 + val2) / 2
case (None, Some(val2)) => val2
case (Some(val1), None) => val1
case (None, None) => default
}
... but if not, the basic idea is that you construct a tuple of options, and then pattern match on the tuple.
This has a benefit of explicitly capturing all the four potential cases + having support from the complier - since Option is a sealed trait, compiler can check and ensure that all the potential branches of pattern match are covered.
You could treat the Options as Seq:
val o: Option[Double]
val p: Option[Double]
val default: Double
val s = o.toSeq ++ p.toSeq
val avg = s.reduceOption(_ + _).getOrElse(default) / 1.max(s.size)
val v = List(opt1, opt2).flatten
if (v.nonEmpty) {
v.sum / v.size
} else {
<default value>
}
This can be extended to work with any number of optional values.
Another possibility:
def avg(left: Option[Double], right: Option[Double])(default: => Double): Double =
left.flatMap(a => right.map(b => (a + b) / 2))
.orElse(left)
.orElse(right)
.getOrElse(default)
You flatMap over the left option: if it's not empty, you take the right option and map its content and average with the content of the left option. If either option is empty, the result is None, so you can defined either left or right as fallback values with orElse. Finally, the result is retrieved with getOrElse and if both inputs where empty, the default is returned.
You can adapt this to adopt any behavior. To make a function that throws if both options are empty you can do the following:
val assertAvg = avg(_ : Option[Double], _ : Option[Double])(sys.error("both operands are empty"))
This works because the type of throw expressions is Nothing, which is a subtype of any other type (including Double), i.e. it can be returned as a result of any expression, regardless the expected type.
The code (and some tests) are available here on Scastie.
In my opinion you should keep average in option and grab default afterwards.
def avgOpt(of:Option[Double]*) = {
val s = of.flatten
s.reduceOption(_ + _).map(_ / s.size)
}
avgOpt(Some(5), None, None).getOrElse(0) //5
avgOpt(Some(5), Some(3), None).getOrElse(0) //4
avgOpt(None, None).getOrElse(0) //0
post("/api/v1/multi_preview/create"){
val html = getParam("html").get
val subject = getParam("subject").get
}
I want to know what exactly the .get method does in scala. getParam() is already returning the parameters to the post hit . I know that .get will make it easier as we dont have to "match" to check for null values as it will automotically thrown an exception in the former case.
Is there more to it than meets the eye?
It's usually a function on Options (i.e. Some or None). It gets you the contained element if it exists, otherwise it throws a NoSuchElementException.
https://www.scala-lang.org/api/current/scala/Option.html
scala> val x:Option[Int] = Some(42)
x: Option[Int] = Some(42)
scala> x.get
res2: Int = 42
scala> None.get
java.util.NoSuchElementException: None.get
at scala.None$.get(Option.scala:322)
... 32 elided
As a side note, you should try to avoid using get because it lands you back in the land of null-pointer exceptions. Instead, try to use getOrElse, or continue to use your Option value through higher-order functions like map, filter, fold, reduce etc.
Here is an example of how you can use it to your advantage:
scala> def foo(opt:Option[Int]) = opt map (_+2) filter (_%2 == 0) map (_+1)
foo: (opt: Option[Int])Option[Int]
scala> foo(Some(40))
res4: Option[Int] = Some(43)
scala> foo(Some(41))
res5: Option[Int] = None
scala> foo(None)
res6: Option[Int] = None
You can just pretend that the value is always specified if you don't "touch" it directly.
I suppose that's some Scalatra related code, if that's the case, getParam return an Option. Options are a wrapper around types that allow you to avoid having to check for nulls (and other kind of utilities too), in fact a value wrapped in an Option can be Some, in which case you can use get to access the value, e.g.
val someString = Option("some text")
println(someString.get) // prints "some text"
Or can be a None in which case when calling get you get an exception, wether a value is a Some or None can be determined via param match
someOption match {
case Some(value) => doSomething(value)
case None => doSomethingElse()
}
Or using isDefined which returns true if it's Some, false if it's None.
Note that your code could throw exceptions since you call get without knowing if it's a Some or None, you should use getOrElse which returns the value the Option holds if there's any, or a default specified parameter:
val someNone = Option(null)
println(someNone.getOrElse("some default")) // prints "some default"
I am currently working on a project with Scala and it seems I don't fully understand Scala's Typesystem :-/
I have the following situation:
def reviews(id: Int) = Action { implicit request =>
Ok(html.products.reviews(
reviewlist,
reviewlist
.find(review => review.id == id)
.getOrElse(reviewlist.headOption)
))
}
Unfortunately the compiler says, he cannot convert Product to Option[Review], so I changed the code
reviewlist
.find(review => review.id == id)
.getOrElse(reviewlist.headOption)
with
id match {
case 0 => reviewlist.headOption
case id => reviewlist.find(review => review.id == id)
}
which seems to work now, even though its not exactly the same thing as it does, for example, not show the first record anymore if an invalid review id is being submitted. it will then pretend, that there are no reviews available yet.
I then broke the problem down to a veeery simple sample:
val a: Option[Int] = Some(1).getOrElse(Some(1))
So, has anyone an idea, why the expression on the right side is not of the type Option[Int]?? Both, Some(1) and None inherit directly from Option and this expression is actually Some(1) in any or am I wrong?
Interestinly enough
val a: Option[Int] = None.getOrElse(None)
works, but all other combinations do not...
You wanted:
val a: Option[Int] = Some(1).orElse(Some(1))
Because
x.getOrElse(y)
will return 1 if x is Some(1) or y (which is Some(1)) if x is None, or speaking in code:
if (Some(1).isDefined) 1 else Some(1)
The type signature of Option.getOrElse is
getOrElse[B >: A](default: ⇒ B): B
That means that when you call getOrElse on an Option[A], it is going to try to return you something of type A. If the type of default (B) isn't the same as A, it is going to look for the closest shared ancestor of A and B. In your case, A and B are Option[Int] and Int. The best the compiler can do is Any.
An Option value has two representations, a good value (Some(...)) or a bad value (None).
With getOrElse you can reduce an Option to the type contained by it.
Imagine it as being a process of unpacking the value, removing it from the container.
In this process of unpacking, the Option is stripped and only the type contained by it is returned,
so in your example you really have this:
val a int = Some(1).getOrElse(2) // 1
And to do what you want is:
val b Option[Int] = Some(1).orElse(Some(2)) // Some(1)
In Groovy language, it is very simple to check for null or false like:
groovy code:
def some = getSomething()
if(some) {
// do something with some as it is not null or emtpy
}
In Groovy if some is null or is empty string or is zero number etc. will evaluate to false. What is similar concise method of testing for null or false in Scala?
What is the simple answer to this part of the question assuming some is simply of Java type String?
Also another even better method in groovy is:
def str = some?.toString()
which means if some is not null then the toString method on some would be invoked instead of throwing NPE in case some was null. What is similar in Scala?
What you may be missing is that a function like getSomething in Scala probably wouldn't return null, empty string or zero number. A function that might return a meaningful value or might not would have as its return an Option - it would return Some(meaningfulvalue) or None.
You can then check for this and handle the meaningful value with something like
val some = getSomething()
some match {
case Some(theValue) => doSomethingWith(theValue)
case None => println("Whoops, didn't get anything useful back")
}
So instead of trying to encode the "failure" value in the return value, Scala has specific support for the common "return something meaningful or indicate failure" case.
Having said that, Scala's interoperable with Java, and Java returns nulls from functions all the time. If getSomething is a Java function that returns null, there's a factory object that will make Some or None out of the returned value.
So
val some = Option(getSomething())
some match {
case Some(theValue) => doSomethingWith(theValue)
case None => println("Whoops, didn't get anything useful back")
}
... which is pretty simple, I claim, and won't go NPE on you.
The other answers are doing interesting and idiomatic things, but that may be more than you need right now.
Well, Boolean cannot be null, unless passed as a type parameter. The way to handle null is to convert it into an Option, and then use all the Option stuff. For example:
Option(some) foreach { s => println(s) }
Option(some) getOrElse defaultValue
Since Scala is statically type, a thing can't be "a null or is empty string or is zero number etc". You might pass an Any which can be any of those things, but then you'd have to match on each type to be able to do anything useful with it anyway. If you find yourself in this situation, you most likely are not doing idiomatic Scala.
In Scala, the expressions you described mean that a method called ? is invoked on an object called some. Regularly, objects don't have a method called ?. You can create your own implicit conversion to an object with a ? method which checks for nullness.
implicit def conversion(x: AnyRef) = new {
def ? = x ne null
}
The above will, in essence, convert any object on which you call the method ? into the expression on the right hand side of the method conversion (which does have the ? method). For example, if you do this:
"".?
the compiler will detect that a String object has no ? method, and rewrite it into:
conversion("").?
Illustrated in an interpreter (note that you can omit . when calling methods on objects):
scala> implicit def any2hm(x: AnyRef) = new {
| def ? = x ne null
| }
any2hm: (x: AnyRef)java.lang.Object{def ?: Boolean}
scala> val x: String = "!!"
x: String = "!!"
scala> x ?
res0: Boolean = true
scala> val y: String = null
y: String = null
scala> y ?
res1: Boolean = false
So you could write:
if (some ?) {
// ...
}
Or you could create an implicit conversion into an object with a ? method which invokes the specified method on the object if the argument is not null - do this:
scala> implicit def any2hm[T <: AnyRef](x: T) = new {
| def ?(f: T => Unit) = if (x ne null) f(x)
| }
any2hm: [T <: AnyRef](x: T)java.lang.Object{def ?(f: (T) => Unit): Unit}
scala> x ? { println }
!!
scala> y ? { println }
so that you could then write:
some ? { _.toString }
Building (recursively) on soc's answer, you can pattern match on x in the examples above to refine what ? does depending on the type of x. :D
If you use extempore's null-safe coalescing operator, then you could write your str example as
val str = ?:(some)(_.toString)()
It also allows you to chain without worrying about nulls (thus "coalescing"):
val c = ?:(some)(_.toString)(_.length)()
Of course, this answer only addresses the second part of your question.
You could write some wrapper yourself or use an Option type.
I really wouldn't check for null though. If there is a null somewhere, you should fix it and not build checks around it.
Building on top of axel22's answer:
implicit def any2hm(x: Any) = new {
def ? = x match {
case null => false
case false => false
case 0 => false
case s: String if s.isEmpty => false
case _ => true
}
}
Edit: This seems to either crash the compiler or doesn't work. I'll investigate.
What you ask for is something in the line of Safe Navigation Operator (?.) of Groovy, andand gem of Ruby, or accessor variant of the existential operator (?.) of CoffeeScript. For such cases, I generally use ? method of my RichOption[T], which is defined as follows
class RichOption[T](option: Option[T]) {
def ?[V](f: T => Option[V]): Option[V] = option match {
case Some(v) => f(v)
case _ => None
}
}
implicit def option2RichOption[T](option: Option[T]): RichOption[T] =
new RichOption[T](option)
and used as follows
scala> val xs = None
xs: None.type = None
scala> xs.?(_ => Option("gotcha"))
res1: Option[java.lang.String] = None
scala> val ys = Some(1)
ys: Some[Int] = Some(1)
scala> ys.?(x => Some(x * 2))
res2: Option[Int] = Some(2)
Using pattern matching as suggested in a couple of answers here is a nice approach:
val some = Option(getSomething())
some match {
case Some(theValue) => doSomethingWith(theValue)
case None => println("Whoops, didn't get anything useful back")
}
But, a bit verbose.
I prefer to map an Option in the following way:
Option(getSomething()) map (something -> doSomethingWith(something))
One liner, short, clear.
The reason to that is Option can be viewed as some kind of collection – some special snowflake of a collection that contains either zero elements or exactly one element of a type and as as you can map a List[A] to a List[B], you can map an Option[A] to an Option[B]. This means that if your instance of Option[A] is defined, i.e. it is Some[A], the result is Some[B], otherwise it is None. It's really powerful!