理解内的Either的值是否与模式匹配? [英] Pattern match on value of Either inside a for comprehension?

查看:99
本文介绍了理解内的Either的值是否与模式匹配?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的理解力:

for {
      (value1: String, value2: String, value3: String) <- getConfigs(args)
      // more stuff using those values
}

getConfigs返回一个Either[Throwable, (Seq[String], String, String)],当我尝试编译时出现此错误:

getConfigs returns an Either[Throwable, (Seq[String], String, String)] and when I try to compile I get this error:

value withFilter is not a member of Either[Throwable,(Seq[String], String, String)]

如何在理解中使用此方法(返回Either)?

How can I use this method (that returns an Either) in the for comprehension?

推荐答案

像这样:

for {
   tuple <- getConfigs()
} println(tuple)

开个玩笑,我认为这是一个有趣的问题,但它的名字被误命名了. 问题(见上文)不是因为无法理解,而是在Either内无法进行for理解内的模式匹配.

Joking aside, I think that is an interesting question but it is misnamed a bit. The problem (see above) is not that for comprehensions are not possible but that pattern matching inside the for comprehension is not possible within Either.

有关如何翻译理解的文档,但他们没有不能涵盖所有情况.据我所知,这里并没有涵盖这一点.因此,我在"Scala编程"(第二版)实例中进行了查找(因为这是我站在枯树旁的那个版本).

There is documentation how for comprehensions are translated but they don't cover each case. This one is not covered there, as far as I can see. So I looked it up in my instance of "Programming in Scala" -- Second Edition (because that is the one I have by my side on dead trees).

有一个子章节生成器中的翻译模式",这就是如上所述的问题.它列出了两种情况:

There is a subchapter "Translating patterns in generators", which is what is the problem here, as described above. It lists two cases:

这正是我们的情况:

for ((x1, …, xn) <- expr1) yield expr2

应翻译为expr1.map { case (x1, …, xn) => expr2). 当您选择代码并执行理解的Desugar"操作时,IntelliJ正是这样做的.耶! …但这使它在我眼中变得更加奇怪,因为经过解密的代码实际上运行没问题.

should translate to expr1.map { case (x1, …, xn) => expr2). Which is exactly what IntelliJ does, when you select the code and do an "Desugar for comprehension" action. Yay! … but that makes it even weirder in my eyes, because the desugared code actually runs without problems.

因此,这种情况是(imho)匹配的情况,但不是正在发生的情况.至少不是我们观察到的.嗯?!

So this case is the one which is (imho) matching the case, but is not what is happening. At least not what we observed. Hm?!

for (pat <- expr1) yield expr2

翻译为

expr1 withFilter {
  case pat => true
  case _ => false
} map {
  case pat => expr2
}

现在有一个withFilter方法! 这种情况完全说明了错误消息,以及为什么无法在Either中进行模式匹配.

where there is now an withFilter method! This case totally explains the error message and why pattern matching in an Either is not possible.

本章最终引用了 scala语言规范(不过,这是我现在停下来的地方.

The chapter ultimately refers to the scala language specification (to an older one though) which is where I stop now.

抱歉,我不能完全回答这个问题,但希望我能在这里暗示问题根源是什么.

So I a sorry I can't totally answer that question, but hopefully I could hint enough what is the root of the problem here.

那么,为什么Either有问题,为什么不提出withFilter方法,而TryOption呢? 因为filter从容器"(可能是全部")中删除元素,所以我们需要一些表示空容器"的东西.

So why is Either problematic and doesn't propose an withFilter method, where Try and Option do? Because filter removes elements from the "container" and probably "all", so we need something that is representing an "empty container".

对于Option来说很容易,这显然是None.也很容易例如List.对于Try来说并不是那么容易,因为有多个Failure,每个都可以容纳一个特定的异常.但是,有很多失败发生在这个地方:

That is easy for Option, where this is obviously None. Also easy for e.g. List. Not so easy for Try, because there are multiple Failure, each one can hold a specific exception. However there are multiple failures taking this place:

  • NoSuchElementException
  • UnsupportedOperationException
  • NoSuchElementException and
  • UnsupportedOperationException

,这就是为什么Try[X]运行但Either[Throwable, X]不能运行的原因. 这几乎是同一回事,但并非完全相同. Try知道LeftThrowable,库作者可以利用它.

and which is why Try[X] runs, but an Either[Throwable, X] does not. It's almost the same thing, but not entirely. Try knows that Left are Throwable and the library authors can take advantage out of it.

但是,在Either(现在是右偏)上,空"情况是Left情况;这是通用的.因此,用户可以确定它是哪种类型,因此库作者无法为每种可能的左值选择通用实例.

However on an Either (which is now right biased) the "empty" case is the Left case; which is generic. So the user determines which type it is, so the library authors couldn't pick generic instances for each possible left.

我认为这就是为什么Either不提供现成的withFilter以及表达失败的原因.

I think this is why Either doesn't provide an withFilter out-of-the-box and why your expression fails.

顺便说一句.

expr1.map { case (x1, …, xn)  => expr2) }

情况行之有效,因为它在调用堆栈上抛出了MatchError,从而避免了问题……这本身可能是一个更大的问题.

case works, because it throws an MatchError on the calling stack and panics out of the problem which… in itself might be a greater problem.

哦,对于那些足够勇敢的人来说:到目前为止,我还没有使用过"Monad"这个词,因为Scala没有用于它的数据结构,但是理解却没有它.但也许引用不会对您造成伤害: Additive Monads 具有此零值,这恰恰是Either在这里遗漏的内容,也是我试图在直觉"部分中赋予一些含义的内容.

Oh and for the ones that are brave enough: I didn't use the "Monad" word up until now, because Scala doesn't have a datastructure for it, but for-comprehensions work just without it. But maybe a reference won't hurt: Additive Monads have this "zero" value, which is exactly what Either misses here and what I tried to give some meaning in the "intuition" part.

这篇关于理解内的Either的值是否与模式匹配?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆