相关疑难解决方法(0)

Scala中Iterator和Stream之间的区别?

似乎Iterator和Stream都是懒惰的,并且允许您将元素保留在心脏的内容中.这两者有什么区别?

scala

57
推荐指数
2
解决办法
9397
查看次数

如何在Scala中使用Stream.cons编写非泄漏尾递归函数?

当编写在Stream(s)上运行的函数时,存在不同的递归概念.第一个简单的意义在编译器级别上不是递归的,因为如果不立即计算尾部,那么函数会立即返回,但返回的流是递归的:

final def simpleRec[A](as: Stream[A]): Stream[B] = 
  if (a.isEmpty) Stream.empty              
  else someB(a.head) #:: simpleRec(a.tail) 
Run Code Online (Sandbox Code Playgroud)

上述递归概念不会引起任何问题.第二个是在编译器级别上真正的尾递归:

@tailrec
final def rec[A](as: Stream[A]): Stream[B] = 
  if (a.isEmpty) Stream.empty              // A) degenerated
  else if (someCond) rec(a.tail)           // B) tail recursion
  else someB(a.head) #:: rec(a.tail)       // C) degenerated
Run Code Online (Sandbox Code Playgroud)

这里的问题是C)编译器将该情况检测为非tailrec调用,即使没有执行实际调用.这可以通过将流尾部分解为辅助函数来避免:

@tailrec
final def rec[A](as: Stream[A]): Stream[B] = 
  if (a.isEmpty) Stream.empty              
  else if (someCond) rec(a.tail)          // B)
  else someB(a.head) #:: recHelp(a.tail)  

@tailrec
final def recHelp[A](as: Stream[A]): Stream[B] = 
  rec(as)
Run Code Online (Sandbox Code Playgroud)

在编译时,这种方法最终会导致内存泄漏.由于尾递归rec最终是从recHelp …

recursion memory-leaks scala stream

14
推荐指数
1
解决办法
2336
查看次数

特征中定义的Scala尾递归流处理器函数保持对流头的引用

在以下情况

trait T {

 @tailrec
 def consume[A](as: Stream[A]): Unit = {
    if (as.isEmpty) ()
    else consume(as.tail)
  }
 }

object O extends T
Run Code Online (Sandbox Code Playgroud)

主叫O.consume(Range(1, N).toStream)N足够大的,程序将运行的存储器,或者至少将消耗O(N),而不是所需要的O(1).

functional-programming scala stream

10
推荐指数
1
解决办法
1344
查看次数