如何将Akka源转换为scala.stream

如何将Akka源转换为scala.stream,scala,akka-stream,scala-streams,Scala,Akka Stream,Scala Streams,我已经有了一个Source[T],但我需要将它传递给一个需要流[T]的函数 我可以.run源代码并将所有内容具体化为一个列表,然后对结果执行.toStream,但这会删除我想要保留的惰性/流特性 这是实现这一目标的唯一途径还是我遗漏了什么 编辑: 在阅读了弗拉基米尔的评论后,我认为我在以错误的方式处理我的问题。下面是一个简单的示例,说明我拥有什么以及我想要创建什么: // Given a start index, returns a list from startIndex to startIn

我已经有了一个
Source[T]
,但我需要将它传递给一个需要
流[T]
的函数

我可以
.run
源代码并将所有内容具体化为一个列表,然后对结果执行
.toStream
,但这会删除我想要保留的惰性/流特性

这是实现这一目标的唯一途径还是我遗漏了什么

编辑

在阅读了弗拉基米尔的评论后,我认为我在以错误的方式处理我的问题。下面是一个简单的示例,说明我拥有什么以及我想要创建什么:

// Given a start index, returns a list from startIndex to startIndex+10.  Stops at 50.
def getMoreData(startIndex: Int)(implicit ec: ExecutionContext): Future[List[Int]] = {
  println(s"f running with $startIndex")
  val result: List[Int] = (startIndex until Math.min(startIndex + 10, 50)).toList
  Future.successful(result)
}
因此,
getMoreData
只是模拟一个服务,它通过页面将数据返回给我。 我的第一个目标是创建以下函数:

def getStream(startIndex: Int)(implicit ec: ExecutionContext): Stream[Future[List[Int]]]
其中,流中的下一个
Future[List[Int]]
元素取决于上一个元素,从流中前一个Future的值中读取最后一个索引。起始索引为0的Eg:

getStream(0)(0) would return Future[List[0 until 10]]
getStream(0)(1) would return Future[List[10 until 20]]
... etc
一旦我有了这个函数,我想创建第二个函数来进一步将它映射到一个简单的
流[Int]
。例如:

def getFlattenedStream(stream: Stream[Future[List[Int]]]): Stream[Int]

Streams开始觉得对于这个工作来说是错误的工具,我应该只编写一个简单的循环。我喜欢流的想法,因为消费者可以映射/修改/使用他们认为合适的流,而不需要制作人知道它。

Scala流是在
getStream
中完成任务的好方法;以下是构建您所需内容的基本方法:

def getStream(startIndex : Int)
             (implicit ec: ExecutionContext): Stream[Future[List[Int]]] = 
  Stream
    .from(startIndex, 10)
    .map(getMoreData)
事情变得棘手的地方是使用
getflattedstream
函数。可以消除
列表[Int]
值周围的
Future
包装,但它需要
wait.result
函数调用,这通常是错误的

通常情况下,最好对未来进行操作,并允许异步操作自行进行。如果你分析你的最终需求/目标,通常没有必要等待未来

但是,如果你绝对必须放弃未来,那么下面是可以实现它的代码:

val awaitDuration = 10 Seconds

def getFlattenedStream(stream: Stream[Future[List[Int]]]): Stream[Int] = 
  stream
    .map(f => Await.result(f, awaitDuration))
    .flatten

Scala Streams是在
getStream
中完成任务的好方法;以下是构建您所需内容的基本方法:

def getStream(startIndex : Int)
             (implicit ec: ExecutionContext): Stream[Future[List[Int]]] = 
  Stream
    .from(startIndex, 10)
    .map(getMoreData)
事情变得棘手的地方是使用
getflattedstream
函数。可以消除
列表[Int]
值周围的
Future
包装,但它需要
wait.result
函数调用,这通常是错误的

通常情况下,最好对未来进行操作,并允许异步操作自行进行。如果你分析你的最终需求/目标,通常没有必要等待未来

但是,如果你绝对必须放弃未来,那么下面是可以实现它的代码:

val awaitDuration = 10 Seconds

def getFlattenedStream(stream: Stream[Future[List[Int]]]): Stream[Int] = 
  stream
    .map(f => Await.result(f, awaitDuration))
    .flatten

我不确定这是不是个好主意。当您想要从
流中获取下一个元素,而具体化的反应流还不能提供它时,您认为您的
流应该如何运行?应该如何处理错误?
的使用者在完成具体化的反应流时应该如何关闭它?我认为回答这些问题是可能的,但由此产生的抽象将是漏洞百出和笨拙的。我创建了
Source[T]
,因为我需要从url获取
T
,这意味着我有一个
Future[T]
。我想我应该使用
mapsync
来解决这个问题。我想我真正想要的是将
流[Future[T]]
转换为
流[T]
,只在实际需要更多的时候调用url。我是否完全走错了方向?问题中的一些代码示例不会有什么坏处……我不确定这是否是个好主意。当您想要从
流中获取下一个元素,而具体化的反应流还不能提供它时,您认为您的
流应该如何运行?应该如何处理错误?
的使用者在完成具体化的反应流时应该如何关闭它?我认为回答这些问题是可能的,但由此产生的抽象将是漏洞百出和笨拙的。我创建了
Source[T]
,因为我需要从url获取
T
,这意味着我有一个
Future[T]
。我想我应该使用
mapsync
来解决这个问题。我想我真正想要的是将
流[Future[T]]
转换为
流[T]
,只在实际需要更多的时候调用url。我是否完全走错了方向?问题中的一些代码示例不会有什么坏处……问题的关键在于
。只有在我们提前知道索引是什么的情况下,from(startIndex,10)
才有效。然而,我想要的是,下一个指数(本例中为10)必须由上一个未来的结果确定。流中的每个步骤都必须等待前一个将来完成,然后才能进行计算。问题的关键在于
。只有在我们提前知道索引将是什么的情况下,from(startIndex,10)
才能起作用。然而,我想要的是,下一个指数(本例中为10)必须由上一个未来的结果确定。流中的每个步骤都必须等待前一个将来完成,然后才能进行计算。