将内容添加到序列的scala计时问题
我有一个问题涉及scala中的范围界定。我有这样一个函数:将内容添加到序列的scala计时问题,scala,playframework,Scala,Playframework,我有一个问题涉及scala中的范围界定。我有这样一个函数: def getElements(id: Int): Seq[Element] = { var test = "" dto.getElementIds(id).map { elementIds => { test += " hello " elementIds.foreach(elementId => dto.getElement(elementId).map {
def getElements(id: Int): Seq[Element] = {
var test = ""
dto.getElementIds(id).map {
elementIds => {
test += " hello "
elementIds.foreach(elementId => dto.getElement(elementId).map {
case Some(element) => test += " hi "
println("ThirdPrint: " + test)
})
println("SecondPrint: " + test)
}
}
println("FirstPrint: " + test)
}
假设“elementsIds”的长度为2。
控制台显示:
首次打印:
你好
第三点:你好
第三点:你好
scala为什么要这么做?我假设第三次打印首先执行。当我看到第一张照片时,“嗨”已经不见了。为什么最后一行代码先执行?
我和斯里克和期货公司合作,这和它有关系吗?谢谢
更新
谢谢,很好用。
是否可以返回一个seq?像这样:
def getElements(id: Int): Future[Seq[Element]] = {
var mySequence: Seq[Element] = Seq()
val elementsIds: Future[Seq[Int]] = dto.getElementIds(id)
var test = ""
val elementsF = elementsIds.flatMap {
elementIds => {
test += " hello "
val idsAsElements: Seq[Future[Element]] = elementIds.map(elementId => dto.getElement(elementId).collect {
case Some(element) => mySequence = mySequence :+ element
})
val idsAsElementsF: Future[Seq[Element]] = Future.sequence(idsAsElements)
idsAsElementsF.onComplete(_ => println("SecondPrint: " + test))
idsAsElementsF
}
}
elementsF.onComplete(_ => println("FirstPrint: " + test))
elementsF
}
当IDASElements为“onComplete”时,是否可以返回“mySequence”
输出:
第三点:你好
第三点:你好
第三点:你好
第二印:你好,你好
你好,你好
输出:
第三点:你好
第三点:你好
第三点:你好
第二印:你好,你好
FirstPrint:hello-hi是的,这不是一个好的解决方案。您应该避免在代码中阻塞,除非是在可能的最高级别(
main
method)。而且,可变状态是不好的,特别是当与并发(未来)结合使用时
您的函数应该返回一个Future
。类似的方法会起作用(我不确定我是否正确地猜测了代码的意图-您的函数声明为返回Seq[Element]
,但编写为返回单元
…我假设,您真正想要返回的是对每个id调用getElement
的结果):
我删除了您的打印输出,因为我不确定它们的用途(因为对dto.getElement的调用也是并行进行的,所以不清楚您希望将这些字符串打印在何处以及打印顺序)
您可以通过在末尾添加另一个转换来模拟“预期输出”,例如:
.andThen { case Success(results) =>
val str = results.foldLeft("hello") { case (a,b) =>
println("ThirdPrint: " + a + " hi")
a + " hi"
}
println("SecondPrint: " + str)
println("FirstPrint: " + str
}
是的,这不是一个好的解决方案。您应该避免在代码中阻塞,除非是在可能的最高级别(
main
method)。而且,可变状态是不好的,特别是当与并发(未来)结合使用时
您的函数应该返回一个Future
。类似的方法会起作用(我不确定我是否正确地猜测了代码的意图-您的函数声明为返回Seq[Element]
,但编写为返回单元
…我假设,您真正想要返回的是对每个id调用getElement
的结果):
我删除了您的打印输出,因为我不确定它们的用途(因为对dto.getElement的调用也是并行进行的,所以不清楚您希望将这些字符串打印在何处以及打印顺序)
您可以通过在末尾添加另一个转换来模拟“预期输出”,例如:
.andThen { case Success(results) =>
val str = results.foldLeft("hello") { case (a,b) =>
println("ThirdPrint: " + a + " hi")
a + " hi"
}
println("SecondPrint: " + str)
println("FirstPrint: " + str
}
dto.getElementIds(id)
是否返回一个Future
?你能提供类型吗?是的,未来[Seq[Int]](id),所以它在后台并行线程中运行。当您的FirstPrint
在行中执行时,另一个线程仍在从它获取ID的位置获取这些ID,一旦发生这种情况,就会执行.map
。好的,我如何解决这个问题?解决什么?这是预期的行为。您希望发生什么?是dto.getElementIds(id)
返回一个Future
?你能提供类型吗?是的,未来[Seq[Int]](id),所以它在后台并行线程中运行。当您的FirstPrint
在行中执行时,另一个线程仍在从它获取ID的位置获取这些ID,一旦发生这种情况,就会执行.map
。好的,我如何解决这个问题?解决什么?这是预期的行为。您希望发生什么?如果使用。请不要忘记。map您必须覆盖所有情况。map{case Some(a)=>…}在none上失败您希望从函数接收第一个完成的idsalements并跳过其他项吗?我希望附加返回值(Some(element))如下所示:mySequence=mySequence:+element
fromval-idsalements:Seq[Future[element]]=elementIds.map(elementId=>dto.getElement(elementId)。收集{…}
并在列表完成后返回该列表。如果需要“完成后的列表”,您可以执行wait.result(elementsF,duration)在上面的代码中。但是这是一个坏主意,这个函数必须返回Future,否则会阻塞主线程。如果使用var是一个瓶颈,并且需要提高性能,那么使用var只有一个原因。使用Await.result有两个原因。第一个是调试代码,第二个是单元测试。没有其他方法替代吗ad of await?如果您使用,请不要忘记。map您必须覆盖所有情况。map{case Some(a)=>…}在none上失败您想从函数接收第一个完成的idsalements并跳过其他吗?我想附加返回值(Some(element)),如下所示:mySequence=mySequence:+element
fromval idsalements:Seq[Future[Element]]=elementId.map(elementId=>dto.getElement(elementId)。收集{…}
并在列表完成后返回该列表。如果需要“完成后的列表”,可以执行Wait.result(elementsF,duration)在上面的代码中。但是这是一个坏主意,这个函数必须返回Future,否则会阻塞主线程。如果使用var是一个瓶颈,并且需要提高性能,那么使用var只有一个原因。使用Await.result有两个原因。第一个是调试代码,第二个是单元测试。没有其他方法替代吗等待的广告?
.andThen { case Success(results) =>
val str = results.foldLeft("hello") { case (a,b) =>
println("ThirdPrint: " + a + " hi")
a + " hi"
}
println("SecondPrint: " + str)
println("FirstPrint: " + str
}