[英]Unexpected scala.MatchError
I have a method with the following definition : 我有以下定义的方法:
def userPosts(userId: String): Future[List[Post]]
I would like to have a method which returns cached date or calls userPosts
if there is no cached data. 我想有一个方法,如果没有缓存的数据,它可以返回缓存的日期或调用userPosts
。 I've prepared something like this: 我准备了这样的东西:
def cachedUserPosts(userId: String): Future[List[Post]] = {
for {
cached <- bucket.get[List[Post]]("posts_" + userId)
} yield {
cached match {
case Some(list) => list
case None => userPosts(userId) match {
case list:List[Post] => list
}
}
}
}
I have an error: 我有一个错误:
[error] play - Cannot invoke the action, eventually got an error: scala.MatchError: scala.concurrent.impl.Promise$DefaultPromise@23cf4a0c (of class scala.concurrent.impl.Promise$DefaultPromise)
play.api.Application$$anon$1: Execution exception[[MatchError: scala.concurrent.impl.Promise$DefaultPromise@23cf4a0c (of class scala.concurrent.impl.Promise$DefaultPromise)]]
at play.api.Application$class.handleError(Application.scala:296) ~[play_2.11-2.3.6.jar:2.3.6]
at play.api.DefaultApplication.handleError(Application.scala:402) [play_2.11-2.3.6.jar:2.3.6]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$3$$anonfun$applyOrElse$4.apply(PlayDefaultUpstreamHandler.scala:320) [play_2.11-2.3.6.jar:2.3.6]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$3$$anonfun$applyOrElse$4.apply(PlayDefaultUpstreamHandler.scala:320) [play_2.11-2.3.6.jar:2.3.6]
at scala.Option.map(Option.scala:145) [scala-library-2.11.2.jar:na]
Caused by: scala.MatchError: scala.concurrent.impl.Promise$DefaultPromise@23cf4a0c (of class scala.concurrent.impl.Promise$DefaultPromise)
at models.Post$$anonfun$fastUserPosts$1.apply(Post.scala:130) ~[classes/:na]
at models.Post$$anonfun$fastUserPosts$1.apply(Post.scala:126) ~[classes/:na]
at scala.util.Success$$anonfun$map$1.apply(Try.scala:236) ~[scala-library-2.11.2.jar:na]
at scala.util.Try$.apply(Try.scala:191) ~[scala-library-2.11.2.jar:na]
at scala.util.Success.map(Try.scala:236) ~[scala-library-2.11.2.jar:na]
2015-07-26 19:33:24.211 INFO net.spy.memcached.auth.AuthThread: Authenticated to 192.168.10.42/192.168.10.42:11210
Do you have any idea what's going on? 你知道发生了什么吗?
You are pattern matching on a Future
, if we try an analogous pattern match in the console : 如果我们在控制台中尝试类似的模式匹配,则您正在Future
上进行模式匹配:
val p = Promise[Int]
val f = p.future
p.success(5) // fulfill the promise
Pattern matching on f
gives us : f
上的模式匹配给我们:
scala> f match { case i: Int => i }
<console>:15: error: pattern type is incompatible with expected type;
found : Int
required: scala.concurrent.Future[Int]
f match { case i: Int => i }
^
Your userPosts
function returns a Future[List[Post]]
and you can't pattern match on the future directly to get the List[Post]
. 您的userPosts
函数返回Future[List[Post]]
,您无法直接在Future[List[Post]]
上进行模式匹配以获取List[Post]
。 You can find more information on working with Future
on the Scala website . 您可以在Scala网站上找到有关使用Future
更多信息。
Lets fix your cachedUserPosts
function. 让我们修复您的cachedUserPosts
函数。 Your version could also be written as ( does not compile ): 您的版本也可以写成( 不编译 ):
bucket.get[List[Post]]("posts_" + userId) map ( cached => cached match {
// List[Post] in Future.map => Future[List[Post]]
case Some(list) => list
// userPosts already gives us a Future[List[Post]]
// We could have used Await.result(userPosts(userId), 5.seconds)
// to get the List[Post] from the Future, but then we would be blocking
case None => userPosts(userId)
})
If we convert the map
into a flatMap
we can return a Future[List[Post]]
, but then we would also need to return a Future[List[Post]]
in the Some
case, which can easily be done using Future.successful
: 如果将map
转换为flatMap
我们可以返回Future[List[Post]]
,但在Some
情况下,我们还需要返回Future[List[Post]]
,这可以使用Future.successful
轻松完成。 :
bucket.get[List[Post]]("posts_" + userId) flatMap ( cached => cached match {
// List[Post] to Future[List[Post]] using Future.successful
case Some(list) => Future.successful(list)
case None => userPosts(userId)
})
We could clean this up a little bit, by using map
/ getOrElse
instead of pattern matching on the Option
: 通过使用map
/ getOrElse
而不是Option
上的模式匹配,我们可以稍微清理一下:
def cachedUserPosts(userId: String): Future[List[Post]] =
bucket.get[List[Post]]("posts_" + userId).flatMap { cached =>
cached.map(list => Future.successful(list))
.getOrElse(userPosts(userId))
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.