10

the bellow code :

scala> class A {
 |     def hi = "Hello from A"
 |     override def toString = getClass.getName
 | }
defined class A

scala> val a = new A()
a: A = A

scala> a.toString
res10: String = A

scala> println(s"${a.toString}")
$line31.$read$$iw$$iw$A

It is printing ok when using a.toString expression, not when using println(s"${a.toString}"). The problem is getClass.getName. In other cases it works nice.

Thanks in advance for any help

dk14
  • 22,206
  • 4
  • 51
  • 88
Juan Salvador
  • 407
  • 9
  • 15
  • this problem is only with Scala repl. on Ammonite repl everything works fine – Nagarjuna Pamu Sep 15 '16 at 16:43
  • Ammonite REPL output `scala> class A { override def toString = getClass.getName } defined class A scala> val a = new A() a: A = $sess.cmd0$A scala> a.toString res2: String = "$sess.cmd0$A" scala> println(s"""${a.toString}""") $sess.cmd0$A` – Nagarjuna Pamu Sep 15 '16 at 16:44
  • This definitely looks like a repl caveat – Jatin Sep 15 '16 at 18:46
  • Yes ... the problem is REPL .... it's a problem as it doesn't look natural behaivor and the result is not the expected one – Juan Salvador Sep 15 '16 at 20:45
  • If we run this code as a online programa (scala myprog.scala) the we get the spected result. So the problem is in REPL class A { override def toString: String = getClass.getName } object Date { def main(args: Array[String]) { println(new A().toString) } } – Juan Salvador Sep 19 '16 at 20:11

4 Answers4

6

REPL filters its output to hide template wrappings.

$ scala
Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_92).
Type in expressions for evaluation. Or try :help.

scala> class A
defined class A

scala> val a = new A
a: A = A@4926097b

scala> a.getClass
res0: Class[_ <: A] = class A

scala> $intp.isettings.
allSettings   deprecation   deprecation_=   maxAutoprintCompletion   maxPrintString   toString   unwrapStrings

scala> $intp.isettings.unwrapStrings = false
$intp.isettings.unwrapStrings: Boolean = false

scala> a.getClass
res1: Class[_ <: A] = class $line3.$read$$iw$$iw$A

You can also compare output clipping:

scala> (1 to 1000).mkString
res2: String = 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629...
scala> println((1 to 1000).mkString)
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000

Scroll right to see the ellipsis on the first line.

som-snytt
  • 39,429
  • 2
  • 47
  • 129
  • `$intp.isettings.unwrapStrings = false ` And then: `scala> println(new A) //prints $line3.$read$$iw$$iw$A` – Jatin Sep 15 '16 at 19:12
  • @Jatin Not sure what you're demonstrating. As I showed, REPL filters its own output, not anything else. – som-snytt Sep 15 '16 at 21:51
5

Since names of classes inside REPL are different, REPL needs to convert internal names back. It does it well enough when displaying strings, but fails when string is passed to an external method, e.g. println or toList:

scala> a.toString
res1: String = A

scala> a.toString.toList
res2: List[Char] = List($, l, i, n, e, 4, ., $, r, e, a, d, $, $, i, w, $, $, i, w, $, A)

scala> "$line4.$read$$iw$$iw$A"
res3: String = A
Victor Moroz
  • 9,167
  • 1
  • 19
  • 23
  • 1
    What is interesting is `val x = a.toString; println(x)` also prints `$line3.$read$$iw$$iw$A` – Jatin Sep 15 '16 at 18:33
  • 1
    But, List(a.toString) gives List(A) – Samar Sep 15 '16 at 19:25
  • 1
    @Samar Because `List(a.toString)` is a `List[String]`, and REPL knows that `String` should be replaced when needed. – Victor Moroz Sep 15 '16 at 21:04
  • 1
    @Jatin When you _display_ `x` in REPL it will replace `x`'s value with `A`, `println` doesn't know about replacement. The real value of `x` is `$line3.$read$$iw$$iw$A` and won't change when copying. – Victor Moroz Sep 15 '16 at 21:07
  • To be clear, "convert internal names back" really means "strip strings that look like internal cruft from output", which is more crude than somehow detecting that `toString` results in an internal string and then subverting it. – som-snytt Sep 16 '16 at 20:35
4

Run the scala repl using: scala -Xprint:parser

Then run the successive commands. The output $line3.$read$$iw$$iw$A represents the path to the A object. $line is a package, $read and $iw are objects under which the object A is nested.

For the case of println(s"${a.toString}")

scala> println(s"${a.toString}")
[[syntax trees at end of                    parser]] // <console>
package $line5 {
  object $read extends scala.AnyRef {
    def <init>() = {
      super.<init>();
      ()
    };
    object $iw extends scala.AnyRef {
      def <init>() = {
        super.<init>();
        ()
      };
      import $line3.$read.$iw.$iw.A;
      import $line4.$read.$iw.$iw.a;
      object $iw extends scala.AnyRef {
        def <init>() = {
          super.<init>();
          ()
        };
        val res0 = println(StringContext("", "").s(a.toString))
      }
    }
  }
}

[[syntax trees at end of                    parser]] // <console>
package $line5 {
  object $eval extends scala.AnyRef {
    def <init>() = {
      super.<init>();
      ()
    };
    lazy val $result = $line5.$read.$iw.$iw.res0;
    lazy val $print: String = {
      $line5.$read.$iw.$iw;  
      ""   <-- // SOMETHING OFF HERE! NO OUTPUT STRING BEING GENERATED?
    }
  }
}

$line3.$read$$iw$$iw$A

Now for the case of a.toString:

scala> a.toString
[[syntax trees at end of                    parser]] // <console>
package $line6 {
  object $read extends scala.AnyRef {
    def <init>() = {
      super.<init>();
      ()
    };
    object $iw extends scala.AnyRef {
      def <init>() = {
        super.<init>();
        ()
      };
      import $line3.$read.$iw.$iw.A;
      import $line4.$read.$iw.$iw.a;
      object $iw extends scala.AnyRef {
        def <init>() = {
          super.<init>();
          ()
        };
        val res1 = a.toString
      }
    }
  }
}

[[syntax trees at end of                    parser]] // <console>
package $line6 {
  object $eval extends scala.AnyRef {
    def <init>() = {
      super.<init>();
      ()
    };
    lazy val $result = $line6.$read.$iw.$iw.res1;
    lazy val $print: String = {
      $line6.$read.$iw.$iw;  // *CORRECTLY GENERATES THE RESULT STRING.*
      "".$plus("res1: String = ").$plus(scala.runtime.ScalaRunTime.replStringOf($line6.$read.$iw.$iw.res1, 1000))
    }
  }
}

res1: String = A
Samar
  • 2,091
  • 1
  • 15
  • 18
  • This does not answer the question. `a.toString` prints `a`. `println(a.toString)` prints `$line3....` – Jatin Sep 15 '16 at 18:41
  • 1
    As seen in the $eval objects (which generates the result string to be shown in the repl) for both the cases, the repl is generating the string to be shown differently for the two cases. Not sure why its doing that yet. – Samar Sep 15 '16 at 19:12
  • Thank you, I can see where the problem is. The problem is not fixed but clearly I can see it's location – Juan Salvador Sep 15 '16 at 20:49
  • Normally, `$eval.$print` is a string representation of the computed value. But if the result type is `Unit`, it doesn't output a string. Try `scala> ()` at the prompt. Not exactly sure how this helped the OP, but SO works in mysterious ways. – som-snytt Sep 15 '16 at 21:48
  • @som-snytt: so in the above output, `val res0 = println(StringContext("", "").s(a.toString))` is the statement responsible for the print to console in the first case? – Samar Sep 16 '16 at 03:45
  • 1
    Yes, that's just the code you entered. If you don't assign it to a variable, it will assign to a synthetic like res0. The REPL prints the value of $print, which lazily evaluates $read. – som-snytt Sep 16 '16 at 04:47
-1

It is the way REPL is compiling A. In a simple app like below there are no issues
Each line in the REPL is wrapped into it's own package.. and that auto generated package name is what you see prepended to class name A.

object ScalaApp extends App {

      class A {
        def hi = "Hello from A"
        override def toString = getClass.getName
      }

      val a = new A()

      println(a.toString)

      println(s"${a.toString}")
    }
Apurva Singh
  • 4,534
  • 4
  • 33
  • 42