Curious
Curious

Reputation: 921

scala Map with Option/Some gives match error

The following code is producing run time error as below. Could reason why the following error. Please explain.

Exception in thread "main" scala.MatchError: Some(Some(List(17))) (of class scala.Some) at com.discrete.CountingSupp$.$anonfun$tuplesWithRestrictions1$1(CountingSupp.scala:43)

def tuplesWithRestrictions1(): (Int, Map[Int, Option[List[Int]]]) = {
    val df = new DecimalFormat("#")
    df.setMaximumFractionDigits(0)
    val result = ((0 until 1000) foldLeft[(Int, Map[Int, Option[List[Int]]])] ((0, Map.empty[Int, Option[List[Int]]]))) {
      (r: (Int, Map[Int, Option[List[Int]]]), x: Int) => {
        val str = df.format(x).toCharArray
        if (str.contains('7')) {
          import scala.math._
          val v = floor(log10(x)) - 1
          val v1 = (pow(10, v)).toInt
          val m: Map[Int, Option[List[Int]]] = (r._2).get(v1) match {
            case None => r._2 + (v1 -> Some(List(x)))
            case Some(xs: List[Int]) => r._2 updated(x, Some(x::xs))
          }
          val f = (r._1 + 1, m)
          f
        } else r
      }
    }
    result
  }

Upvotes: 0

Views: 745

Answers (2)

Curious
Curious

Reputation: 921

def tuplesWithRestrictions1(): (Int, Map[Int, List[Int]]) = {
    val df = new DecimalFormat("#")
    df.setMaximumFractionDigits(0)
    val result = ((0 until 1000) foldLeft[(Int, Map[Int, List[Int]])] ((0, Map.empty[Int, List[Int]]))) {
      (r: (Int, Map[Int, List[Int]]), x: Int) => {
        val str = df.format(x).toCharArray
        if (str.contains('7')) {
          import scala.math._
          val v = floor(log10(x))
          val v1 = (pow(10, v)).toInt
          val m: Map[Int, List[Int]] = (r._2).get(v1) match {
            case Some(xs: List[Int]) => r._2 updated(v1, x :: xs)
            case None => r._2 + (v1 -> List(x))
          }
          val f = (r._1 + 1, m)
          f
        } else r
      }
    }
    result
  }

Upvotes: 0

Nagarjuna Pamu
Nagarjuna Pamu

Reputation: 14825

Return type of .get on map is

get(k: K): Option[V]

Scala doc

  /** Optionally returns the value associated with a key.
   *
   *  @param  key    the key value
   *  @return an option value containing the value associated with `key` in this map,
   *          or `None` if none exists.
   */
  def get(key: K): Option[V]

Now,

r._2.get(v1) returns an option of Value. So the final return type would be Option[Option[List[Int]]].

You are trying to pattern match for Option[T] but the real value type is Option[Option[Int]] which is not captured in the match.

  1. Use r._2(v1) to extract the value and match. Throws exception when v1 is not found in map.

  2. Match inside map providing default value.

    r._2.get(k1).map {
      case None => r._2 + (v1 -> Some(List(x)))
      case Some(value) => r._2 updated(x, Some(x::xs))
    }.getOrElse(defaultValue)
    

Upvotes: 1

Related Questions