0

I'm new to Scala and I was playing around with the Array.tabulate method. I am getting a StackOverFlowError when executing this simplified piece of code snippet (originally a dp problem).

  import Lazy._

  class Lazy[A](x: => A) {
    lazy val value = x
  }

  object Lazy {
    def apply[A](x: => A) = new Lazy(x)
    implicit def fromLazy[A](z: Lazy[A]): A = z.value
    implicit def toLazy[A](x: => A): Lazy[A] = Lazy(x)
  }

  def tabulatePlay(): Int = {
    lazy val arr: Array[Array[Lazy[Int]]] = Array.tabulate(10, 10) { (i, j) =>
      if (i == 0 && j == 0)
        0 // some number
      else
        arr(0)(0)
    }
    arr(0)(0)
  }

Debugging, I noticed that since arr is lazy and when it reaches the arr(0)(0) expression it tries to evaluate it by calling the Array.tabulate method again -- infinitely over and over.

What am i doing wrong? (I updated the code snippet since I was basing it off the solution given in Dynamic programming in the functional paradigm in particular Antal S-Z's answer )

Community
  • 1
  • 1
xxtommoxx
  • 309
  • 3
  • 13

3 Answers3

0

You have effectively caused an infinite recursion. You simply can't reference a lazy val from within its own initialization code. You need to compute arr(0)(0) separately.

ghik
  • 10,706
  • 1
  • 37
  • 50
0

I'm not sure why you are trying to access arr before it's built, tabulate seems to be used to fill the array with a function - calling arr would always result in infinite recursion.

See Rex's example here (and a vote for him), perhaps that will help.

In a multidimensional sequence created with tabulate, is the innermost seq the 1. dimension?

Community
  • 1
  • 1
LaloInDublin
  • 5,379
  • 4
  • 22
  • 26
0

I was able to solve this by wrapping arr(0)(0) in Lazy so it is evaluated as a call-by-name parameter, thereby not evaluating arr in the tabulate method. The code that I referenced was automatically converting it using implicits (the binary + operator), so it wasn't clear cut.

 def tabulatePlay(): Int = {
    lazy val arr: Array[Array[Lazy[Int]]] = Array.tabulate(10, 10) { (i, j) =>
      if (i == 0 && j == 0)
        1 // some number
      else
        new Lazy(arr(0)(0))
    }
    arr(0)(0)
  }

Thanks all.

xxtommoxx
  • 309
  • 3
  • 13