Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 合并两个流(有序)以获得最终排序的流_Scala_Stream_Lazy Evaluation_Tail Recursion - Fatal编程技术网

Scala 合并两个流(有序)以获得最终排序的流

Scala 合并两个流(有序)以获得最终排序的流,scala,stream,lazy-evaluation,tail-recursion,Scala,Stream,Lazy Evaluation,Tail Recursion,例如,如何合并两个排序整数流?我认为这是非常基本的,但我发现这一点都不琐碎。下面的一个不是尾部递归的,当流较大时,它将堆栈溢出 def merge(as: Stream[Int], bs: Stream[Int]): Stream[Int] = { (as, bs) match { case (Stream.Empty, bss) => bss case (ass, Stream.Empty) => ass case (a #:: ass, b #:: b

例如,如何合并两个排序整数流?我认为这是非常基本的,但我发现这一点都不琐碎。下面的一个不是尾部递归的,当流较大时,它将堆栈溢出

def merge(as: Stream[Int], bs: Stream[Int]): Stream[Int] = {
  (as, bs) match {
    case (Stream.Empty, bss) => bss
    case (ass, Stream.Empty) => ass
    case (a #:: ass, b #:: bss) =>
      if (a < b) a #:: merge(ass, bs)
      else b #:: merge(as, bss)
  }
}
def合并(as:Stream[Int],bs:Stream[Int]):Stream[Int]={
(as,bs)匹配{
案例(Stream.Empty,bss)=>bss
案例(ass,Stream.Empty)=>ass
案例(a::ass,b::bss)=>
如果(a
我们可能希望通过引入累加器将其转化为尾部递归。然而,如果我们预先挂起累加器,我们只会得到一个相反顺序的流;如果我们用连接(#::)附加累加器,它就不再是懒惰(严格的)


这里的解决方案是什么?谢谢

将评论转换为答案,您的合并没有问题

它根本不是递归的——任何一个对merge的调用都会返回一个新流,而不需要任何其他对merge的调用
a#::merge(ass,bs)
返回包含第一个元素
a
的流,其中
merge(ass,bs)
将在需要时被调用以评估流的其余部分

所以


很好用。没有堆栈溢出。

“下面的一个不是尾部递归的,当流较大时,它将堆栈溢出。”为什么?递归不是“真实的”,因为“递归”调用中的合并还不应该计算。也就是说,您的代码根本不是递归的,因为它从
if
的任一分支返回一个新流?还是我误解了?谢谢你的回答。问题是,因为它不是尾部递归的,所以上面的示例代码将发出OOM,因为我猜堆栈帧将包含对流头部的引用。我不确定这是否正确(但我没有测试它)。一旦访问流中的下一个元素,上一个堆栈帧/闭包将不被引用,并且是GC;'d、 我想。
val m = merge(Stream.from(1,2), Stream.from(2, 2))
//> m  : Stream[Int] = Stream(1, ?)
m.drop(10000000).take(1)
//> res0:     scala.collection.immutable.Stream[Int] = Stream(10000001, ?)