Jak badać obiekty / typy / itp. z Scala REPL?

Pracuję ze Scalą już od jakiegoś czasu i napisałem z nią program wiersza 10 000+, ale nadal jestem zdezorientowany przez niektóre wewnętrzne działania. Przyszedłem do Scali z Pythona, po tym, jak już dobrze poznałem Java, C i Lisp, ale mimo to działa powoli, a ogromnym problemem jest frustrująca trudność, którą często spotykam, próbując zbadać wewnętrzne działanie obiektów / typów / klasy / etc. używając Scala REPL w porównaniu z Pythonem. W Pythonie możesz badać dowolny obiektfoo (typ, obiekt w zmiennej globalnej, funkcja wbudowana itp.) przy użyciufoo aby zobaczyć, co ta rzecz ocenia,type(foo) aby pokazać jego typ,dir(foo) aby powiedzieć, jakie metody możesz wywołać ihelp(foo) aby uzyskać wbudowaną dokumentację. Możesz nawet robić takie rzeczyhelp("re") znaleźć dokumentację o nazwie pakieture (który przechowuje obiekty i metody wyrażenia regularnego), nawet jeśli nie ma z nim skojarzonego obiektu.

W Scali możesz spróbować przeczytać dokumentację online, przejrzeć kod źródłowy w bibliotece itp., Ale często może to być bardzo trudne dla rzeczy, w których nie wiesz, gdzie lub nawet są (i często duży kawałek do odgryzienia, biorąc pod uwagę obszerną hierarchię typów) - rzeczy pływają w różnych miejscach (pakietscala, Predef, różne niejawne konwersje, takie jak symbole:: które są prawie niemożliwe dla Google). REPL powinien być sposobem na bezpośrednie odkrywanie, ale w rzeczywistości rzeczy są o wiele bardziej tajemnicze. Powiedz, że widziałem odniesienie dofoo gdzieś, ale nie mam pojęcia, co to jest. Najwyraźniej nie ma czegoś takiego jak „przewodnik do systematycznego badania Scala za pomocą REPL”, ale to, co połączyłem po wielu próbach i błędach:

Jeślifoo jest wartością (która prawdopodobnie obejmuje rzeczy zapisane w zmiennych plus obiekty towarzyszące i inne Scala)objects), możesz ocenićfoo bezpośrednio. Powinno to powiedzieć, jaki jest typ i wartość wyniku. Czasami wynik jest pomocny, czasem nie.Jeślifoo to wartość, której możesz użyć:type foo uzyskać jego typ. (Niekoniecznie oświecenie.) Jeśli użyjesz tego w wywołaniu funkcji, otrzymasz typ wartości zwracanej, bez wywoływania funkcji.Jeślifoo to wartość, której możesz użyćfoo.getClass uzyskać jego klasę. (Często bardziej oświecająca niż poprzednia, ale w jaki sposób klasa obiektu różni się od jej typu?)Dla klasyfoo, możesz użyćclassOf[foo], chociaż nie jest oczywiste, co oznacza wynik.Teoretycznie możesz użyć:javap foo zdemontować klasę - która powinna być najbardziej użyteczna ze wszystkich, ale dla mnie nie działa całkowicie i jednolicie.Czasami trzeba układać rzeczy z komunikatów o błędach.

Przykład użycia awarii:javap:

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

Przykład oświecającego komunikatu o błędzie:

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, spróbujmy teraz prostego przykładu.

scala> 5
res63: Int = 5

scala> :type 5
Int

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

Wystarczająco proste ...

Wypróbujmy teraz kilka prawdziwych przypadków, w których nie jest to takie oczywiste:

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

scala> :type Predef
type

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

Co to znaczy? Dlaczego jest typPredef po prostutype, podczas gdy klasa jestscala.Predef$? Rozumiem, że $ to sposób, w jaki obiekty towarzyszące przechodzą na Javę ... ale dokumenty Scala w Google mówią mi o tymPredef jestobject Predef extends LowPriorityImplicits - jak mogę to wywnioskować z REPL? A jak mogę sprawdzić, co w niej jest?

OK, spróbujmy czegoś innego:

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, to sprawiło, że byłem beznadziejnie zdezorientowany i ostatecznie musiałem przeczytać kod źródłowy, żeby to wszystko zrozumieć.

Moje pytania to:

Jaki jest zalecany najlepszy sposób od prawdziwych ekspertów Scali na używanie REPL do zrozumienia obiektów, klas, metod itp. Scali, a przynajmniej zbadanie ich najlepiej, jak można to zrobić z REPL?Jak mogę uzyskać:javap pracujesz z REPL dla wbudowanych rzeczy? (Czy nie powinno to działać domyślnie?)

Dzięki za wszelkie oświecenie.

questionAnswers(4)

yourAnswerToTheQuestion