Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to investigate objects/types/etc. from Scala REPL?
    primarykey
    data
    text
    <p>I've been working with Scala for a while now and have written a 10,000+ line program with it, but I'm still confused by some of the inner workings. I came to Scala from Python after already having intimate familiarity with Java, C and Lisp, but even so it's been slow going, and a huge problem is the frustrating difficulty I've often found when trying to investigate the inner workings of objects/types/classes/etc. using the Scala REPL as compared with Python. In Python you can investigate any object <code>foo</code> (type, object in a global variable, built-in function, etc.) using <code>foo</code> to see what the thing evaluates to, <code>type(foo)</code> to show its type, <code>dir(foo)</code> to tell you the methods you can call on it, and <code>help(foo)</code> to get the built-in documentation. You can even do things like <code>help("re")</code> to find out the documentation on the package named <code>re</code> (which holds regular-expression objects and methods), even though there isn't an object associated with it.</p> <p>In Scala, you can try and read the documentation online, go look up the source code to the library, etc., but this can often be very difficult for things where you don't know where or even what they are (and it's often a big chunk to bite off, given the voluminous type hierarchy) -- stuff is floating around in various places (package <code>scala</code>, <code>Predef</code>, various implicit conversions, symbols like <code>::</code> that are nearly impossible to Google). The REPL should be the way to explore directly, but in reality, things are far more mysterious. Say that I've seen a reference to <code>foo</code> somewhere, but I have no idea what it is. There's apparently no such thing as a "guide to systematically investigating Scala thingies with the REPL", but the following is what I've pieced together after a great deal of trial and error:</p> <ol> <li>If <code>foo</code> is a value (which presumably includes things stored in variables plus companion objects and other Scala <code>object</code>s), you can evaluate <code>foo</code> directly. This ought to tell you the type and value of the result. Sometimes the result is helpful, sometimes not.</li> <li>If <code>foo</code> is a value, you can use <code>:type foo</code> to get its type. (Not necessarily enlightening.) If you use this on a function call, you get the type of the return value, without calling the function.</li> <li>If <code>foo</code> is a value, you can use <code>foo.getClass</code> to get its class. (Often more enlightening than the previous, but how does an object's class differ from its type?)</li> <li>For a class <code>foo</code>, you can use <code>classOf[foo]</code>, although it's not obvious what the result means.</li> <li>Theoretically, you can use <code>:javap foo</code> to disassemble a class -- which should be the most useful of all, but fails entirely and uniformly for me.</li> <li>Sometimes you have to piece things together from error messages.</li> </ol> <p>Example of failure using <code>:javap</code>:</p> <pre><code>scala&gt; :javap List Failed: Could not find class bytes for 'List' </code></pre> <p>Example of enlightening error message:</p> <pre><code>scala&gt; assert &lt;console&gt;:8: error: ambiguous reference to overloaded definition, both method assert in object Predef of type (assertion: Boolean, message: =&gt; Any)Unit and method assert in object Predef of type (assertion: Boolean)Unit match expected type ? assert ^ </code></pre> <p>OK, now let's try a simple example.</p> <pre><code>scala&gt; 5 res63: Int = 5 scala&gt; :type 5 Int scala&gt; 5.getClass res64: java.lang.Class[Int] = int </code></pre> <p>Simple enough ...</p> <p>Now, let's try some real cases, where it's not so obvious:</p> <pre><code>scala&gt; Predef res65: type = scala.Predef$@3cd41115 scala&gt; :type Predef type scala&gt; Predef.getClass res66: java.lang.Class[_ &lt;: object Predef] = class scala.Predef$ </code></pre> <p>What does this mean? Why is the type of <code>Predef</code> simply <code>type</code>, whereas the class is <code>scala.Predef$</code>? I gather that the $ is the way that companion objects are shoehorned into Java ... but Scala docs on Google tell me that <code>Predef</code> is <code>object Predef extends LowPriorityImplicits</code> -- how can I deduce this from the REPL? And how can I look into what's in it?</p> <p>OK, let's try another confusing thing:</p> <pre><code>scala&gt; `::` res77: collection.immutable.::.type = :: scala&gt; :type `::` collection.immutable.::.type scala&gt; `::`.getClass res79: java.lang.Class[_ &lt;: object scala.collection.immutable.::] = class scala.collection.immutable.$colon$colon$ scala&gt; classOf[`::`] &lt;console&gt;:8: error: type :: takes type parameters classOf[`::`] ^ scala&gt; classOf[`::`[Int]] res81: java.lang.Class[::[Int]] = class scala.collection.immutable.$colon$colon </code></pre> <p>OK, this left me hopelessly confused, and eventually I had to go read the source code to make sense of this all.</p> <p>So, my questions are:</p> <ol> <li>What's the recommended best way from the true Scala experts of using the REPL to make sense of Scala objects, classes, methods, etc., or at least investigate them as best as can be done from the REPL?</li> <li>How do I get <code>:javap</code> working from the REPL for built-in stuff? (Shouldn't it work by default?)</li> </ol> <p>Thanks for any enlightenment.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload