简体   繁体   中英

Getting StackOverFlowError on example from “Programming in Scala Third Edition” Chapter 10

I'm coping the example classes Element and Spiral from "Programming in Scala Third Edition" Chapter 10. Now I'm trying to run it using "scala Spiral 8" and I get the error:

Exception in thread "main" java.lang.StackOverflowError
at java.base/java.lang.String.(String.java:250)
at java.base/java.lang.String.valueOf(String.java:2802)
at java.base/java.lang.Character.toString(Character.java:7563)
at Element$UniformElement.(Element.scala:9)
at Element$.elem(Element.scala:24)
at Element.heighten(Element.scala:66)
at Element.beside(Element.scala:46)
at Element.widen(Element.scala:59)

And so on...

I'm new to Scala and tyring not to get frustrated and improve, so if you figure it out, please try to describe as best possible how you found the mistake and what it was. Thank you!

Here's the code:

object Element {
  private class ArrayElement(val contents: Array[String]) extends Element

  private class UniformElement(
                                ch: Char,
                                override val height: Int,
                                override val width: Int
                              ) extends Element {
    private val line = ch.toString * width
    def contents: Array[String] = Array.fill(height)(line)
  }

  private class LineElement(s: String) extends Element {
    val contents = Array(s)
    override def width: Int = s.length
    override def height = 1
  }

  def elem(contents: Array[String]): Element = {
    new ArrayElement(contents)
  }

  def elem(ch: Char, height: Int, width: Int): Element = {
    new UniformElement(ch, height, width)
  }

  def elem(line: String): Element = {
    new LineElement(line)
  }
}

import Element.elem
abstract class Element {
  def contents: Array[String]

  def width: Int = contents(0).length
  def height: Int = contents.length

  def above(that: Element): Element = {
    val this1 = this widen that.width
    val that1 = that widen this.width
    elem(this1.contents ++ that1.contents)
  }

  def beside(that: Element): Element = {
    val this1 = this heighten that.height
    val that1 = that heighten this.height
    elem(
      for ((line1, line2) <- this1.contents zip that1.contents)
        yield line1 + line2
    )
  }

  def widen(w: Int): Element = {
    if (w <= width) this
    else {
      val left = elem(' ', (w - width) / 2, height)
      val right = elem(' ', w - width - left.width, height)
      left beside this beside right
    }
  }

  def heighten(h: Int): Element = {
    if (h <= height) this
    else {
      val top = elem(' ', width, (h - height) / 2)
      val bot = elem(' ', width, h - height - top.height)
      top above this above bot
    }
  }

  override def toString: String = contents mkString "\n"
}
import Element.elem
object Spiral {
  val space: Element = elem(" ")
  val corner: Element = elem("+")

  def spiral(nEdges: Int, direction: Int): Element = {
    if (nEdges == 1)
      elem("+")
    else {
      val sp = spiral(nEdges -1, (direction + 3) % 4)
      def verticalBar = elem('|', 1, sp.height)
      def horizontalBar = elem('-', sp.width, 1)
      if (direction == 0)
        (corner beside horizontalBar) above (sp beside space)
      else if (direction == 1)
        (sp above space) beside (corner above verticalBar)
      else if (direction == 2)
        (space beside sp) above (horizontalBar beside corner)
      else
        (verticalBar above corner) beside (space above sp)
    }
  }

  def main(args: Array[String]): Unit = {
    val nSides = args(0).toInt
    println(spiral(nSides, 0))
  }
}

You just inverted the order of the width and height parameters in UniformElement , elem . So, when you called elem from widen and heighten you passed the width for the height and viceversa.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM