Cómo investigar objetos / tipos / etc. de Scala REPL?

He estado trabajando con Scala por un tiempo y he escrito un programa de más de 10,000 líneas, pero todavía estoy confundido por algunos de los trabajos internos. Llegué a Scala desde Python después de tener una familiaridad íntima con Java, C y Lisp, pero aun así ha sido lento, y un gran problema es la dificultad frustrante que a menudo he encontrado al intentar investigar el funcionamiento interno de los objetos / tipos. / clases / etc. utilizando el Scala REPL en comparación con Python. En Python puedes investigar cualquier objeto.foo (tipo, objeto en una variable global, función incorporada, etc.) usandofoo Para ver lo que la cosa evalúa,type(foo) para mostrar su tipo,dir(foo) para indicarle los métodos a los que puede recurrir, yhelp(foo) para obtener la documentación incorporada. Incluso puedes hacer cosas comohelp("re") para averiguar la documentación en el paquete llamadore (que contiene objetos y métodos de expresión regular), aunque no hay ningún objeto asociado con él.

En Scala, puede probar y leer la documentación en línea, ir a buscar el código fuente a la biblioteca, etc., pero esto puede ser muy difícil para las cosas en las que no sabe dónde o qué es lo que están (y con frecuencia un pedazo grande para morder, dada la jerarquía de tipos voluminosos) - las cosas están flotando en varios lugares (paquetescala, Predef, varias conversiones implícitas, símbolos como:: que son casi imposibles para google). El REPL debería ser la forma de explorar directamente, pero en realidad, las cosas son mucho más misteriosas. Di que he visto una referencia afoo En algún lugar, pero no tengo idea de lo que es. Aparentemente, no existe tal cosa como una "guía para investigar sistemáticamente las cosas de Scala con el REPL", pero lo siguiente es lo que he reunido después de una gran cantidad de prueba y error:

Sifoo es un valor (que presumiblemente incluye cosas almacenadas en variables más objetos complementarios y otros Scala)objects), se puede evaluarfoo directamente. Esto debería decirle el tipo y el valor del resultado. A veces el resultado es útil, a veces no.Sifoo es un valor que puedes usar:type foo para obtener su tipo. (No necesariamente esclarecedor). Si usa esto en una llamada de función, obtiene el tipo del valor de retorno, sin llamar a la función.Sifoo es un valor que puedes usarfoo.getClass para obtener su clase. (A menudo es más esclarecedor que el anterior, pero ¿en qué se diferencia la clase de un objeto de su tipo?)Para una clasefoo, puedes usarclassOf[foo], aunque no es obvio lo que significa el resultado.Teóricamente, puedes usar:javap foo para desmontar una clase, que debería ser la más útil de todas, pero para mí es un fracaso total y uniforme.A veces tienes que juntar cosas de mensajes de error.

Ejemplo de falla usando:javap:

scala> :javap List
Failed: Could not find class bytes for 'List'

Ejemplo de mensaje de error esclarecedor:

scala> assert
<console>:8: error: ambiguous reference to overloaded definition,
both method assert in object Predef of type (assertion: Boolean, message: => Any)Unit
and  method assert in object Predef of type (assertion: Boolean)Unit
match expected type ?
              assert
              ^

Bien, ahora probemos un ejemplo simple.

scala> 5
res63: Int = 5

scala> :type 5
Int

scala> 5.getClass
res64: java.lang.Class[Int] = int

Suficientemente simple ...

Ahora, probemos algunos casos reales, donde no es tan obvio:

scala> Predef
res65: type = scala.Predef$@3cd41115

scala> :type Predef
type

scala> Predef.getClass
res66: java.lang.Class[_ <: object Predef] = class scala.Predef$

¿Qué significa esto? ¿Por qué es el tipo dePredef simplementetype, mientras que la clase esscala.Predef$? Supongo que $ es la forma en que los objetos complementarios se encuadran en Java ... pero los documentos de Scala en Google me dicen quePredef esobject Predef extends LowPriorityImplicits - ¿Cómo puedo deducir esto del REPL? ¿Y cómo puedo ver lo que hay en él?

OK, vamos a intentar otra cosa confusa:

scala> `::`
res77: collection.immutable.::.type = ::

scala> :type `::`
collection.immutable.::.type

scala> `::`.getClass
res79: java.lang.Class[_ <: object scala.collection.immutable.::] = class scala.collection.immutable.$colon$colon$

scala> classOf[`::`]
<console>:8: error: type :: takes type parameters
              classOf[`::`]
                      ^

scala> classOf[`::`[Int]]
res81: java.lang.Class[::[Int]] = class scala.collection.immutable.$colon$colon

De acuerdo, esto me dejó completamente confundido y, finalmente, tuve que leer el código fuente para entender todo esto.

Entonces, mis preguntas son:

¿Cuál es la mejor manera recomendada por los verdaderos expertos de Scala de usar el REPL para dar sentido a los objetos, clases, métodos, etc. de Scala, o al menos investigarlos lo mejor que se pueda hacer desde el REPL?Como lo consigo:javap ¿Trabajando desde el REPL para cosas incorporadas? (¿No debería funcionar por defecto?)

Gracias por cualquier iluminación.

Respuestas a la pregunta(4)

Su respuesta a la pregunta