Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala implicit for Option containing Map

Tags:

scala

implicit

I am trying to write the following implicit:

implicit class ExtractOrElse[K, V](o: Option[Map[K, V]]) {
  def extractOrElse(key: K)(f: => V): V = { if (o.isDefined) o.get(key) else f }
}

Which I want to use in this way:

normalizationContexts.extractOrElse(shardId)(defaultNormalizationContext)

to avoid a clunkier syntax (normalizationContexts is an Option[Map[String, NormzalitionContext]]).

Also, let me add that it is intentional that there is only one default value: it will be used if the Option isEmpty, but if the Option isDefined, then the behavior of the Map is not changed, and it will throw an exception if the key is not found - so the default value won't be used in that case, and this is all intentional.

However, I get an error when passing in None in unit tests:

assertEquals(None.extractOrElse('a')(0), 0)

results in:

Error:(165, 37) type mismatch;
 found   : Char('a')
 required: K
  assertEquals(None.extractOrElse('a')(0), 0)

I realize that None is not parametric, as it is defined as:

case object None extends Option[Nothing] {
  def isEmpty = true
  def get = throw new NoSuchElementException("None.get")

What is the best way to make this work?

like image 223
Frank Avatar asked Dec 18 '25 01:12

Frank


1 Answers

Instead of None.extractOrElse(...), try Option.empty[Map[Char, Int]].extractOrElse(...).

If you always use the same types for your test cases, you could also create a type alias in the specs class in order to reduce the clutter:

type OpMap = Option[Map[Char, Int]]
// ...
assertEquals(Option.empty[OpMap].extractOrElse('a')(0), 0)

Just in case, you can use flatMap and getOrElse to achieve the same thing without writing a new method:

val n = Option.empty[Map[String, Int]]
val s = Some(Map("x" → 1, "y" → 2))

n.flatMap(_.get("x")).getOrElse(3)  // 3
s.flatMap(_.get("x")).getOrElse(3)  // 1
s.flatMap(_.get("z")).getOrElse(3)  // 3
like image 176
Roberto Bonvallet Avatar answered Dec 21 '25 07:12

Roberto Bonvallet



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!