[英]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: 为了以防万一,您可以使用
flatMap
和getOrElse
来实现相同的功能,而无需编写新方法:
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
. 类型系统没有足够的关于
K
和V
类型的信息。 There is no way to know what the type of A
would be in the case where your None
was Some[A]
. 在你的
None
是Some[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.