StackOverflowException When Using Iterable


#1

I've created a Level for the 7 Day Roguelike Challenge that is supposed to implement the Iterable<T> interface so I can use all of those cool functions.

enum class FloorType {   Floor   Wall }

class Level(val dimension: Dimension,
           private val level: Array<FloorType>) {
  val width  = dimension.width
  val height = dimension.height
  val area   = width * height

  fun get(point: Point): FloorType {
  return get(point.x, point.y)
  }

  fun get(x: Int, y: Int): FloorType {
  return level[x + y * width]
  }
}

fun Level.iterable(): Iterable<FloorType> {
  return object: Iterable<FloorType> {
  override fun iterator(): Iterator<FloorType> {
           return iterator()
  }
  }
}

fun Level.iterator(): Iterator<FloorType> {
  return object: Iterator<FloorType> {
  var x = 0
  var y = 0

  &nbsp;&nbsp;override fun hasNext(): Boolean {

           return (y != height)
  }

  &nbsp;&nbsp;override fun next(): FloorType {

           val next = get(x, y)

           x += 1
           if (x % width == 0) {
           y += 1
           x = 0
           }

           return next
  }
  }
}


And the failing unit test

class CaveGeneratorSpec: Spek() {{   given("A cave generator with sensible configuration") {   val configurationUrl = javaClass<CaveGeneratorSpec>().getClassLoader()!!.getResource("settings.yml")!!   val configuration = loadConfiguration(configurationUrl.getPath()!!.substring(1))   val caveGenerator = CaveGenerator(configuration)

  &nbsp;&nbsp;on("generating a 50x50 cave") {

           val cave = caveGenerator.generate(Dimension(50, 50))

           it(“should be partially filled with walls”) {
           val numberOfWalls = cave.iterable().count { it == FloorType.Wall }

           assertTrue(numberOfWalls != 0)
           }
  }
  }
}}


With the exception:

java.lang.StackOverflowError      at com.sbg.arena.core.CorePackage$iterable$1.iterator(Level.kt:54)      at com.sbg.arena.core.CorePackage$iterable$1.iterator(Level.kt:54)      at com.sbg.arena.core.CorePackage$iterable$1.iterator(Level.kt:54)      at com.sbg.arena.core.CorePackage$iterable$1.iterator(Level.kt:54)      at com.sbg.arena.core.CorePackage$iterable$1.iterator(Level.kt:54)      at com.sbg.arena.core.CorePackage$iterable$1.iterator(Level.kt:54)      at com.sbg.arena.core.CorePackage$iterable$1.iterator(Level.kt:54)      at com.sbg.arena.core.CorePackage$iterable$1.iterator(Level.kt:54)      at com.sbg.arena.core.CorePackage$iterable$1.iterator(Level.kt:54)

...

CaveGenerator uses a few dependencies which makes it unwieldy to show here. I propose you forgo creating the CaveGenerator and simply create a 2500-large Array:

on("generating a 50x50 cave") {   val random = Random()

  val cave = Level(Dimension(50, 50), Array<FloorType>(2500, {
  if (random.nextInt(100) > 50) FloorType.Wall else FloorType.Floor
  }))

  it(“should be partially filled with walls”) {
  val numberOfWalls = cave.iterable().count { it == FloorType.Wall }

  &nbsp;&nbsp;assertTrue(numberOfWalls != 0)

  }
}


If you want to see the full source, the code is on my GitHub.


#2

fun Level.iterable(): Iterable<FloorType> {   val outer = this   return object: Iterable<FloorType> {   override fun iterator(): Iterator<FloorType> {            return outer.iterator()   }   } }