3
scala> 5 / 0
java.lang.ArithmeticException: / by zero
  ... 28 elided

Twenty eight frames elided for a simple arithmetic expression?! What are these frames, why does Scala need that many to do safe division, and why are they being elided in the first place?

Cory Klein
  • 51,188
  • 43
  • 183
  • 243
  • 1
    Just a guess, wouldn't it make sense that the REPL executing your expression adds some stack levels and would be un-interesting enough to be elided? – Joachim Isaksson Jun 20 '19 at 19:03
  • Yes, that makes perfect sense! – Cory Klein Jun 20 '19 at 19:15
  • It happens for any exception. ```scala> throw new RuntimeException java.lang.RuntimeException ... 28 elided``` – Alonso del Arte Oct 12 '20 at 03:34
  • Though there are ways to get more interesting stack traces ```scala> res2.take(10).toList java.lang.IllegalArgumentException: Dividing -1 by 0 results in an indeterminate number. at fractions.Fraction.dividedBy(Fraction.java:159) at .$anonfun$newtonSqrt$2(:1) at scala.collection.immutable.LazyList$.$anonfun$iterate$2(LazyList.scala:1157) at scala.collection.immutable.LazyList$.$anonfun$iterate$1(LazyList.scala:1156) at scala.collection.immutable.LazyList.scala$collection$immutable$LazyList$$state$lzycompute(LazyList.scala:218) ... 28 elided``` – Alonso del Arte Oct 12 '20 at 03:48
  • Got one with 28 and 29 trying to use a Kotlin class from the Scala REPL... – Alonso del Arte Oct 18 '20 at 04:29

1 Answers1

7
scala> import scala.util.Try
import scala.util.Try

scala> Try(5/0)
res2: scala.util.Try[Int] = Failure(java.lang.ArithmeticException: / by zero)

scala> res2.recover { case e: ArithmeticException => e.printStackTrace }
java.lang.ArithmeticException: / by zero
    at $line8.$read$$iw$$iw$$anonfun$1.apply$mcI$sp(<console>:13)
    at $line8.$read$$iw$$iw$$anonfun$1.apply(<console>:13)
    at $line8.$read$$iw$$iw$$anonfun$1.apply(<console>:13)
    at scala.util.Try$.apply(Try.scala:192)
    at $line8.$read$$iw$$iw$.<init>(<console>:13)
    at $line8.$read$$iw$$iw$.<clinit>(<console>)
    at $line8.$eval$.$print$lzycompute(<console>:7)
    at $line8.$eval$.$print(<console>:6)
    at $line8.$eval.$print(<console>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:786)
    at scala.tools.nsc.interpreter.IMain$Request.loadAndRun(IMain.scala:1047)
    at scala.tools.nsc.interpreter.IMain$WrappedRequest$$anonfun$loadAndRunReq$1.apply(IMain.scala:638)
    at scala.tools.nsc.interpreter.IMain$WrappedRequest$$anonfun$loadAndRunReq$1.apply(IMain.scala:637)
    at scala.reflect.internal.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:31)
    at scala.reflect.internal.util.AbstractFileClassLoader.asContext(AbstractFileClassLoader.scala:19)
    at scala.tools.nsc.interpreter.IMain$WrappedRequest.loadAndRunReq(IMain.scala:637)
    at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:569)
    at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:565)
    at scala.tools.nsc.interpreter.ILoop.interpretStartingWith(ILoop.scala:807)
    at scala.tools.nsc.interpreter.ILoop.command(ILoop.scala:681)
    at scala.tools.nsc.interpreter.ILoop.processLine(ILoop.scala:395)
    at scala.tools.nsc.interpreter.ILoop.loop(ILoop.scala:415)
    at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply$mcZ$sp(ILoop.scala:923)
    at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:909)
    at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:909)
    at scala.reflect.internal.util.ScalaClassLoader$.savingContextLoader(ScalaClassLoader.scala:97)
    at scala.tools.nsc.interpreter.ILoop.process(ILoop.scala:909)
    at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:74)
    at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:87)
    at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:98)
    at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:103)
    at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
res3: scala.util.Try[AnyVal] = Success(())

The elided lines are basically the REPL's overhead of reading a line, compiling it into a class, and constructing an instance of the class, which is where the code written in the REPL is evaluated.

Levi Ramsey
  • 18,884
  • 1
  • 16
  • 30
  • 2
    And it goes without saying that really everything in that stack trace below `scala.util.Try$.apply` is an implementation detail that obscures the part of the stack trace that would be common if you copied into a `main` method and ran it. – Levi Ramsey Jun 20 '19 at 19:07
  • Thank you very much for this answer. I was going to ask a more general question, but this answers it. – Alonso del Arte Oct 12 '20 at 04:01