Como investigar objetos / tipos / etc. da Scala REPL?

Eu tenho trabalhado com Scala por um tempo agora e tenho escrito um programa de 10.000 + line com ele, mas eu ainda estou confuso com alguns dos trabalhos internos. Eu vim para o Scala do Python depois de já ter uma familiaridade íntima com Java, C e Lisp, mas mesmo assim tem sido lento, e um grande problema é a dificuldade frustrante que eu sempre encontrei ao tentar investigar o funcionamento interno de objetos / tipos / classes / etc. usando o Scala REPL em comparação com o Python. Em Python, você pode investigar qualquer objetofoo (tipo, objeto em uma variável global, função embutida, etc.) usandofoo para ver o que a coisa avalia,type(foo) para mostrar seu tipodir(foo) para lhe dizer os métodos que você pode chamar, ehelp(foo) para obter a documentação incorporada. Você pode até fazer coisas comohelp("re") para descobrir a documentação do pacote chamadore (que contém objetos e métodos de expressão regular), mesmo que não haja um objeto associado a ele.

No Scala, você pode tentar ler a documentação on-line, procurar o código-fonte na biblioteca, etc., mas isso pode ser muito difícil para as coisas em que você não sabe onde nem mesmo o que eles são (e é frequente um grande pedaço para morder, dada a hierarquia do tipo volumoso) - o material está flutuando em vários lugares (pacotescala, Predef, várias conversões implícitas, símbolos como:: que são quase impossíveis para o Google). O REPL deve ser o caminho para explorar diretamente, mas, na realidade, as coisas são muito mais misteriosas. Diga que vi uma referência afoo em algum lugar, mas não tenho ideia do que é. Aparentemente, não existe um "guia para investigar sistematicamente as coisas do Scala com o REPL", mas o seguinte é o que eu reuni depois de uma grande quantidade de tentativas e erros:

E sefoo é um valor (que presumivelmente inclui coisas armazenadas em variáveis ​​mais objetos complementares e outros Scalaobjects), você pode avaliarfoo diretamente. Isso deve informar o tipo e o valor do resultado. Às vezes o resultado é útil, às vezes não.E sefoo é um valor, você pode usar:type foo para obter o seu tipo. (Não necessariamente esclarecedor.) Se você usar isso em uma chamada de função, obterá o tipo do valor de retorno, sem chamar a função.E sefoo é um valor, você pode usarfoo.getClass para obter sua classe. (Muitas vezes mais esclarecedor do que o anterior, mas como a classe de um objeto é diferente do seu tipo?)Para uma aulafoo, você pode usarclassOf[foo], embora não seja óbvio o que o resultado significa.Teoricamente, você pode usar:javap foo desmontar uma classe - que deveria ser a mais útil de todas, mas falha inteira e uniformemente para mim.Às vezes você tem que juntar as coisas das mensagens de erro.

Exemplo de falha usando:javap:

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

Exemplo de mensagem de erro esclarecedora:

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
              ^

OK, agora vamos tentar um exemplo simples.

scala> 5
res63: Int = 5

scala> :type 5
Int

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

Simples o suficiente ...

Agora, vamos tentar alguns casos reais, onde não é tão óbvio:

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

scala> :type Predef
type

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

O que isto significa? Por que o tipo dePredef simplesmentetype, enquanto a classe éscala.Predef$? Eu entendo que o $ é o modo como os objetos complementares são usados ​​em Java ... mas os documentos da Scala no Google me dizem quePredef éobject Predef extends LowPriorityImplicits Como posso deduzir isso da REPL? E como posso ver o que há nele?

OK, vamos tentar outra coisa 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

OK, isso me deixou desesperadamente confuso, e eventualmente eu tive que ler o código fonte para entender tudo isso.

Então, minhas perguntas são:

Qual é a melhor maneira recomendada pelos verdadeiros especialistas em Scala de usar o REPL para entender os objetos, classes, métodos, etc. Scala, ou pelo menos investigá-los da melhor maneira possível a partir do REPL?Como eu consigo:javap trabalhando a partir do REPL para material embutido? (Não deveria funcionar por padrão?)

Obrigado por qualquer esclarecimento.

questionAnswers(4)

yourAnswerToTheQuestion