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.