Scala惰性动态规划

Scala惰性动态规划,scala,dynamic-programming,lazy-evaluation,Scala,Dynamic Programming,Lazy Evaluation,因此,我将遵循并实现Scala中的斐波那契示例。以下是我的实现: class Lazy[T] (expr : => T) { lazy val value = expr def apply(): T = value } object Lazy{ def apply[T](expr : => T) = new Lazy({expr}) } def fib(n: Int): Int = { def doFib(i: Int): Lazy[Int] = Lazy {

因此,我将遵循并实现Scala中的斐波那契示例。以下是我的实现:

class Lazy[T] (expr : => T) {
  lazy val value = expr
  def apply(): T = value
}
object Lazy{ def apply[T](expr : => T) = new Lazy({expr}) }

def fib(n: Int): Int = {
  def doFib(i: Int): Lazy[Int] = Lazy {
    if (i <= 2) 1
    else fibs(i - 1)() + fibs(i - 2)()
  }
  lazy val fibs = Array.tabulate[Lazy[Int]](n)(doFib)
  doFib(n).value
}
fib(5)
fibs(i-1)的计算似乎太早,这导致了无限递归。我想知道对于理解语法是否有一个与第一个代码片段相当的

你是对的,“fibs(I-1)计算得太早了”。调用
doFib
时会立即对其进行计算,因为
doFib(i)
需要
fib(i-1)
才能返回任何内容,而这反过来又需要
doFib(i-1)
的返回值等等,以便在构建惰性整数数组时递归完全展开(在调用
doFib(n).value
之前)

如果希望它是惰性的,那么返回一个不需要立即计算fibs(i-1)
lazy

这将产生相同的预期结果

class Lazy[T] (expr : => T) {
  lazy val value = expr
  def apply(): T = value
  def flatMap[A](f: T => Lazy[A]): Lazy[A] = Lazy { f(value).value }
  def map[A](f: T => A): Lazy[A] = Lazy { f(value) }
}
object Lazy{ def apply[T](expr : => T) = new Lazy({expr}) }

def fib(n: Int): Int = {
  def doFib(i: Int): Lazy[Int] =
    if (i <= 2) Lazy(1)
    else for {
      a <- fibs(i - 1)
      b <- fibs(i - 2)
    } yield a + b
  lazy val fibs = Array.tabulate[Lazy[Int]](n)(doFib)
  doFib(n).value
}
fib(5)
class Lazy[T] (expr : => T) {
  lazy val value = expr
  def apply(): T = value
  def flatMap[A](f: T => Lazy[A]): Lazy[A] = Lazy { f(value).value }
  def map[A](f: T => A): Lazy[A] = Lazy { f(value) }
}

object Lazy{ def apply[T](expr : => T) = new Lazy({expr}) }

def fib(n: Int): Int = {
  def doFib(i: Int): Lazy[Int] =
    if (i <= 2) Lazy(1)
    else Lazy{ (for {
        a <- fibs(i - 1)
        b <- fibs(i - 2)
      } yield a + b).value
    }
  lazy val fibs = Array.tabulate[Lazy[Int]](n)(doFib)
  doFib(n).value
}

println(fib(40)) // 102334155
def doFib(i: Int): Lazy[Int] = Lazy {
  if (i <= 2) 1
  else (for {
    a <- fibs(i - 1)
    b <- fibs(i - 2)
  } yield a + b).value
}