在我的method1中,我需要异步调用另一个method2,它返回Option(result1)。那么,如果 result1 为空,我需要异步调用另一个 method3,但如果 result1 不为空,我只需要返回它。
方法如下:
def signIn(username: String): Future[User] = {
for {
foundUser <- userService.findByUsername(username) // this method returns Future[Option[User]],
// foundUser is Option[User]
user <- if (foundUser.isEmpty) {
val newUser = User(username = "User123")
userService.create(newUser).map(Some(_)) // this method returns Future[Option[User]]
}
else
// Here I want to return just foundUser, of course, it is not possible.
// IS THIS APPROACH CORRECT?? DOES THIS LINE CREATE ASYNCHRONOUS CALL?
Future.successful(foundUser)
} yield user
}
Run Code Online (Sandbox Code Playgroud)
问题是:
Future.successful(foundUser)- 上面的代码中这种方法正确吗?此行是否创建异步调用?如果是这样,如何避免呢?我已经异步获取了 …
在学习你Haskell的教程有一个例子使用let列表中理解粘结剂:
calcBmis xs = [bmi | (w, h) <- xs, let bmi = w / h ^ 2, bmi >= 25.0]
Run Code Online (Sandbox Code Playgroud)
该函数采用高度/重量对列表,并返回超出某个限制的相应体质量指数列表,例如:
ghci> calcBmis [(70, 1.85), (50, 2.00), (130, 1.62)]
[49.53513183965858]
Run Code Online (Sandbox Code Playgroud)
这里有趣的是,bmi理解中绑定的值既可以用于保护,也可以用在结果表达式中.我知道如何在Scala中执行类似操作的唯一方法是编写:
def calcBmis(xs : Seq[(Double,Double)]) =
for((w,h) <- xs ; bmi <- Some(w / (h*h)) if bmi >= 25.0) yield bmi
Run Code Online (Sandbox Code Playgroud)
不得不把我的价值包裹在Some这里感觉不对.谁知道更好的方法?
我正在阅读Programming Clojure第2版,在第49页上它涵盖了Clojure的for循环结构,它说它实际上是一个序列理解.
作者建议使用以下代码:
(defn indexed [coll] (map-indexed vector coll))
(defn index-filter [pred col]
(when pred
(for [[idx elt] (indexed col) :when (pred elt)] idx)))
(index-filter #{\a} "aba")
(0 2)
Run Code Online (Sandbox Code Playgroud)
...优于基于Java的命令式示例,并且给出的证据是"通过使用高阶函数......任何函数索引都避免了对变量的所有需求".
什么是"idx","elt",如果它们不是变量?它们是指除累加器之外的变量吗?
另外,为什么#{\ a}而不是"a"?
我有一些代码与几个讨厌的嵌套检查...
我很确定它可以用一个很好的理解来重写,但我对如何混合模式匹配的东西有点困惑
// first tries to find the token in a header: "authorization: ideas_token=xxxxx"
// then tries to find the token in the querystring: "ideas_token=xxxxx"
private def applicationTokenFromRequest(request: Request[AnyContent]): Option[String] = {
val fromHeaders: Option[String] = request.headers.get("authorization")
val tokenRegExp = """^\s*ideas_token\s*=\s*(\w+)\s*$""".r
val tokenFromHeader: Option[String] = {
if (fromHeaders.isDefined) {
val header = fromHeaders.get
if (tokenRegExp.pattern.matcher(header).matches) {
val tokenRegExp(extracted) = header
Some(extracted)
} else {
None
}
} else {
None
}
}
// try to find it in the queryString …Run Code Online (Sandbox Code Playgroud) 从我第一次读到:
for {
harpo<-list1 if harpo.length>0
groucho<-list2
chico<-list3
} yield (harpo, groucho, chico)
Run Code Online (Sandbox Code Playgroud)
翻译成:
list1.filter(_.length>0).flatMap(harpo =>
list2.flatMap(groucho=>list3.map((harpo,groucho,_)))
)
Run Code Online (Sandbox Code Playgroud)
我担心filter, flatMap&返回的不必要的中间集合map。第一个是通过添加withFilter方法在 Scala 2.8(?) 中修复的,我怀疑有一些魔法会根据使用情况改变这些方法的返回类型,因此当用作参数时,flatMap它们返回一个非严格集合,但我找不到任何证据。我的怀疑是对的吗,它并不像乍一看那样无效?
如果有警卫,我如何用于理解?
type Error = String
type Success = String
def csrfValidation(session:Session, body:JsValue):Either[Error,Success] = {
val csrfRet = for (csrfSession <- csrfStateSessionValidation(session).right;
csrfReq <- csrfStateReqBodyValidation(body).right if (csrfSession == csrfReq)) yield (csrfReq)
if (csrfRet.isRight)
Right(csrfRet)
else {
Logger.warn("request and session csrf is not the same")
Left("Oops,something went wrong, request and session csrf is not the same")
}
}
Run Code Online (Sandbox Code Playgroud)
使用它时出现此错误.
'withFilter' method does not yet exist on scala.util.Either.RightProjection[Error,Success], using `filter' method instead
Run Code Online (Sandbox Code Playgroud)
编辑: 我有另一个错误.我认为如果使用guard,它会返回一个选项结果.
[error] type mismatch;
[error] found : Option[scala.util.Either[Nothing,controllers.ProfileApiV1.Success]]
[error] required: …Run Code Online (Sandbox Code Playgroud) 现在,我花了一段时间才弄明白为什么我的递归以某种方式成功地炸毁堆栈.这就是导致这个问题的部分:
scala> for {
| i <- List(1, 2, 3)
| j = { println("why am I evaluated?"); 10 } if false
| } yield (i, j)
why am I evaluated?
why am I evaluated?
why am I evaluated?
res0: List[(Int, Int)] = List()
Run Code Online (Sandbox Code Playgroud)
这不是疯了吗?为什么要评估j = ...它是否结束if false,因此永远不会被使用?
我学到了什么,而不是{ println ... }你有一个递归调用(和递归防护而不是if false),会发生什么.<
为什么?!
我对for理解和flatMap选项非常熟悉.
所以我知道你可以做点什么
val a: Option[_] = for {
foo <- Some(x)
bar <- Some(y)
baz <- Some(z)
} yield baz
Run Code Online (Sandbox Code Playgroud)
Some(z)如果在理解中没有任何内容None,那就给了我,因为它flatMap在每个语句中都做了.
但实际上我正在寻找其他方面的东西.我想穿越到for理解,只要一切None,就像是orElse在for理解.
例如:
val b: Option[_] = for {
foo <- None
bar <- Some(x)
baz <- None
} yield *return the one with some*
Run Code Online (Sandbox Code Playgroud)
有这样的东西,或者最好的方法是什么?
提前致谢!
我有许多函数返回未来,这是一个理解的结果,但我需要在出路时从一些可能的失败中恢复.标准语法似乎将for comprehension捕获为中间结果,如下所示:
def fooBar(): Future[String] = {
val x = for {
x <- foo()
y <- bar(x)
} yield y
x.recover {
case SomeException() => "bah"
}
}
Run Code Online (Sandbox Code Playgroud)
我找到的最好的替代方法是用括号括起整体来理解:
def fooBar(): Future[String] = (for {
x <- foo()
y <- bar(x)
} yield y).recover {
case SomeException() => "bah"
}
Run Code Online (Sandbox Code Playgroud)
这似乎是一种捷径,而不是语法上的改进,所以我想知道是否有更好的方法将恢复编织为理解?
我正在努力以一种很好的 monadic 方式组合一系列异步进程。该过程的每一步都可能失败,因此它正在检索Future[Either[String, T]].
def firstStep(input: Int): Future[Either[String, Long]] = ???
def secondStep(input: Long): Future[Either[String, String]] = ???
def thirdStep(input: String): Future[Either[String, Double]] = ???
Run Code Online (Sandbox Code Playgroud)
鉴于这些功能,我想像这样组合它们
def process(input: Int): Future[Either[String Double]] = {
for{
res1 <- firstStep(input)
res2 <- secondStep(res1)
res3 <- thirdStep(res2)
} yield res3
}
Run Code Online (Sandbox Code Playgroud)
但这不起作用,因为每个部分结果都是一个Either[String, T],而我需要的是它T本身(或者只是停止执行并返回,Left如果是这种情况)。
如何以一种很好的 monadic 方式(使用 for-comprehensions)组合这个函数?