简体   繁体   English

Scala隐含于包含Map的Option

[英]Scala implicit for Option containing Map

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]] ). 避免使用笨重的语法( normalizationContexts是一个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. 另外,让我补充说,故意只有一个默认值:如果Option isEmpty将使用它,但如果Option isDefined ,那么Map的行为不会改变,并且如果找不到密钥 - 因此在这种情况下不会使用默认值,这都是故意的。

However, I get an error when passing in None in unit tests: 但是,在单元测试中传入None时出现错误:

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: 我意识到None不是参数化的,因为它被定义为:

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? 使这项工作的最佳方法是什么?

Instead of None.extractOrElse(...) , try Option.empty[Map[Char, Int]].extractOrElse(...) . 而不是None.extractOrElse(...) ,尝试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: 如果您总是对测试用例使用相同的类型,您还可以在specs类中创建一个类型别名,以减少混乱:

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: 为了以防万一,您可以使用flatMapgetOrElse来实现相同的功能,而无需编写新方法:

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

The type system doesn't have enough information about the types K and V . 类型系统没有足够的关于KV类型的信息。 There is no way to know what the type of A would be in the case where your None was Some[A] . 在你的NoneSome[A]的情况下,无法知道A的类型是什么。

When I create an example with explicit types, the code works as expected: 当我使用显式类型创建示例时,代码按预期工作:

// Like this
val e = new ExtractOrElse(Option.empty[Map[Char, Int]])
e.extractOrElse('a')(0) // Equals 0

// Or like this
val e = new ExtractOrElse[Char, Int](None)
println(e.extractOrElse('a')(0))

// Or like this
val m: Option[Map[Char, Int]] = None
val e = new ExtractOrElse(m)
println(e.extractOrElse('a')(0))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM