理解内的Either的值是否与模式匹配? [英] Pattern match on value of Either inside a for comprehension?
问题描述
我有这样的理解力:
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
方法,而Try
和Option
呢?
因为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
andUnsupportedOperationException
,这就是为什么Try[X]
运行但Either[Throwable, X]
不能运行的原因.
这几乎是同一回事,但并非完全相同. Try
知道Left
是Throwable
,库作者可以利用它.
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屋!