scala Option and datatypes

Viewed 121

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

3 Answers

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

Related