我有一段代码,代码如下:
val e2 = for (e <- elements if condition(expensiveFunction(e))) yield {
expensiveFunction(e)
}
Run Code Online (Sandbox Code Playgroud)
条件对于少数元素是正确的,然后对所有剩余的元素变为假.
不幸的是,这不起作用(即使我忽略性能)因为我elements是一个无限的迭代器.
有没有办法在for-comprehension中使用"break",这样当某个条件成立时它会停止产生元素?否则,计算我的scala-idiomatic方法是e2什么?
假设我有:
val res:Future[Option[Boolean]] = Future(Some(true))
Run Code Online (Sandbox Code Playgroud)
我能做到:
res.map(opt => opt.map(r => print(!r)))
Run Code Online (Sandbox Code Playgroud)
我想对此的理解是:
for {
opt <- res
r <- opt
} yield (print(!r))
Run Code Online (Sandbox Code Playgroud)
但这不起作用!我收到一个错误,即:
error: type mismatch;
found : Option[Unit]
required: scala.concurrent.Future[?]
r <- opt
Run Code Online (Sandbox Code Playgroud)
如何在for comprehension中使用Future [Option [Boolean]]来提取或转换布尔值?
注意:这是我目前使用许多Future [Option [Boolean]]变量的问题的简化,我想在for comprehension中一起使用它们.
object Main extends App {
val p1 = Promise[Option[String]]()
val p2 = Promise[Option[String]]()
val f1 = p1.future
val f2 = p2.future
val res = (for{
file1Opt <- f1
file2Opt <- f2
file1 <- file1Opt
file2 <- file2Opt
} yield {
combineFiles(file1, file2)
}).fallbackTo(Future.successful("Files not found"))
Thread.sleep(2000)
println("XXXXXXXXXXXXXXXXXXX")
p1.success(Some("file one"))
p2.success(Some("file two"))
val finalData = res.map(s =>
s + " " + "add more data to the file"
)
finalData.map(println(_))
def combineFiles(f1: String, f2: String): String = {
f1 + " …Run Code Online (Sandbox Code Playgroud) 在下面的代码中,在for理解中,我可以使用元组取消引用来引用字符串和索引:
val strings = List("a", "b", "c")
for (stringWithIndex <- strings.zipWithIndex) {
// Do something with stringWithIndex._1 (string) and stringWithIndex._2 (index)
}
Run Code Online (Sandbox Code Playgroud)
有没有在斯卡拉语法的方式有stringWithIndex拆分成零件(串和索引)的范围内for理解头,使代码的读者不必在值怀疑stringWithIndex._1和stringWithIndex._2?
我尝试了以下,但它不会编译:
for (case (string, index) <- strings.zipWithIndex) {
// Do something with string and index
}
Run Code Online (Sandbox Code Playgroud) 我刚刚观看了Martin Odersky在Coursera上关于Scala的讲座第6周.在第5讲他说
"...... for的翻译不仅限于列表或序列,甚至是集合;
它完全基于方法map,flatMap和withFilter的存在.
这使您可以为自己的类型使用for语法 - 您只能为这些类型定义map,flatMap和withFilter."
我试图解决的问题是我们有一个批处理过程,它从几个数据库加载数据,组合数据并以某种方式导出结果.数据足够小以适应内存(来自每个源系统的几十万条记录),但足够大以至于考虑性能很重要.
我可以使用传统的内存数据库(如H2)并通过ScalaQuery或类似的方式访问它,但我真正需要的只是一种能够有效地从不同源系统搜索和连接数据的方法 - 等于SQL的索引和JOINs.使用完整的关系数据库+ Scala ORM,可以通过Scala原生的一些数据结构轻松高效地解决问题,这感觉真的很尴尬.
我的第一个天真的方法是一个Vector数据结构(用于快速直接访问)与一个或多个"索引"(可以像数据库系统一样实现为B-Trees).这个组合数据结构的map,flatMap,withFilter方法可以足够智能,如果它们有一个用于查询字段的索引,则可以使用索引 - 或者它们可以有一个"提示"来使用索引.
我只是想知道这些数据结构是否已经存在且可用,还是我需要自己实现它们?是否有Scala的库或集合框架可以解决这个问题?
当我做一个future,或者应用类似的方法onSuccess和map,我能为他们指定的ExecutionContext.
例如,
val f = future {
// code
} executionContext
f.map(someFunction)(executionContext)
f onSuccess {
// code
} executionContext
Run Code Online (Sandbox Code Playgroud)
但是,如果我使用了对未来的理解,我该如何为该yield部分指定ExecutionContext ?
for {
f <- future1
g <- future2
} yield {
// code to be executed after future1 onSuccess and future2 onSuccess
// What ExecutionContext runs this code?
} // (executionContext) here does not work
Run Code Online (Sandbox Code Playgroud)
而且,如果没有指定,ExecutionContext在yield中运行代码是什么?
好.感谢答案,我找到了一些东西.
如果我没有定义或导入隐式 ExecutionContext(如Implicits.global),则for-comprehension不会编译.这意味着,for-comprehension使用隐式ExecutionContext.
那么,如何在没有隐式ExecutionContext的情况下使用for-comprehension,即如何指定?
我试图理解在处理空值并在for-comprehension中键入注释时看起来像是奇怪的行为.
举个例子:
def f(): String = null
for {
a <- Option("hello")
b = f()
} yield (a, b)
Run Code Online (Sandbox Code Playgroud)
结果在预期中:
//> res0: Option[(String, String)] = Some((hello,null))
Run Code Online (Sandbox Code Playgroud)
但是,如果我在类型中添加类型注释 b
def f(): String = null
for {
a <- Option("hello")
b: String = f()
} yield (a, b)
Run Code Online (Sandbox Code Playgroud)
然后我得到一个运行时异常:
//> scala.MatchError: (hello,null) (of class scala.Tuple2)
Run Code Online (Sandbox Code Playgroud)
为什么会这样?在第一个例子中是不是b隐式的类型String?第二个示例中的显式类型注释会发生什么变化?
(注意,示例在Scala 2.11.4中运行)
当我不关心返回值时,我该如何编写代码.
例:
for {
a <- getA // I do not care about a, but I need to wait for the future to finish
b <- getB
} yield (b)
Run Code Online (Sandbox Code Playgroud) 给出以下代码snippelt:
import scala.util.Try
def foo(x:Int) : (Int, String) = {
(x+1, x.toString)
}
def main(args: Array[String]) : Unit = {
val r1: Try[(Int, String)] = for {
v <- Try { foo(3) }
} yield v
val r2: Try[(Int, String)] = for {
(i, s) <- Try { foo(3) } // compile warning refers to this line
} yield (i, s)
}
Run Code Online (Sandbox Code Playgroud)
1.为什么编译上面的代码会抛出以下警告?
`withFilter' method does not yet exist on scala.util.Try[(Int, String)], using `filter' method instead
[warn] (i, s) <- …Run Code Online (Sandbox Code Playgroud) 我有这样的理解:
for {
(value1: String, value2: String, value3: String) <- getConfigs(args)
// more stuff using those values
}
Run Code Online (Sandbox Code Playgroud)
getConfigs返回一个Either[Throwable, (Seq[String], String, String)],当我尝试编译时,我收到此错误:
value withFilter is not a member of Either[Throwable,(Seq[String], String, String)]
Run Code Online (Sandbox Code Playgroud)
如何Either在for comprehension中使用此方法(返回一个)?