1

I am trying to write in Scala a function similar to the Haskell "iterate" function. Given a value x and a function f, iterate should return a Stream composed of the values x, f(x), f(f(x)), etc...

Here is the code I wrote:

object current {
  def iterate[A](f: A => A, x: A): Stream[A] = {
    val res: Stream[A] = x #:: res.map(f)
    return res
  }

  def double(x: Int) = x * 2

  def main(args: Array[String]): Unit = {
    val str: Stream[Int] = iterate(double, 2)
  }
}

When I try to compile it, I get the error:

forward reference extend over the definition of value res (at line 3)

How can I correct my code to generate the proper Stream ?

vkubicki
  • 1,104
  • 1
  • 11
  • 26
  • http://stackoverflow.com/questions/35111887/scala-error-forward-reference-extends-over-definition-of-value-when-code-appe – Victor Moroz Oct 23 '16 at 00:10

3 Answers3

4

I assume you need something like this:

def iterate[A](f: A => A, x: A): Stream[A] =  x #:: iterate(f, f(x))

but for a better type inference I would write it this way:

def iterate[A](x: A)(f: A => A): Stream[A] = x #:: iterate(f(x))(f)

scala> iterate(0)(_ + 1).take(10).force
res0: scala.collection.immutable.Stream[Int] = Stream(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
Victor Moroz
  • 9,167
  • 1
  • 19
  • 23
2

Thank for the two answers. The minimal change to my code for the iterate function to work is simply to add a lazy keyword:

def iterate[A](f: A => A, x: A): Stream[A] = {
  lazy val res: Stream[A] = x #:: res.map(f)
  return res
}
vkubicki
  • 1,104
  • 1
  • 11
  • 26
1

I think this is what you are looking for.

def iterate[A](f: A => A, x: A): Stream[A] = Stream.iterate[A](x)(f)

Now you can use it like this.

def double(x: Int): Int = x * 2

def main(args: Array[String]): Unit = {
  val str: Stream[Int] = iterate(double, 2).take(10)
  str.foreach(print)
}
Jegan
  • 1,721
  • 1
  • 20
  • 25
  • I tried your solution, but I only get this error message: value iterate is not a member of object Stream – vkubicki Oct 21 '16 at 21:06
  • Are you sure? Here is that method. https://github.com/scala/scala/blob/v2.11.8/src/library/scala/collection/immutable/Stream.scala#L1248 – Jegan Oct 21 '16 at 22:03
  • Which means I've reinvented the wheel. At least it's close. – Victor Moroz Oct 21 '16 at 22:38
  • I am using Scala-Ide (http://scala-ide.org/) on Windows. Here is the greeting message on the console: Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_102). The strange thing is that I can define iterate as you do in the Scala console, but I can not compile a code that defines it. – vkubicki Oct 22 '16 at 13:24
  • Check the classpath in your scala-ide and the SDK it uses. And also double check you are using the right imports. Sometimes with auto import it may be using a wrong class. – Jegan Oct 22 '16 at 13:34
  • The error was simply that I created a Stream object in one of my tests, and that shadowed the Stream class provided by Scala. Learning from mistakes... – vkubicki Oct 23 '16 at 10:26