Я работаю с Scala какое-то время и написал с ним 10 000 + линейную программу, но я все еще смущен некоторыми внутренними работами. Я пришел к Scala из Python после того, как уже был знаком с Java, C и Lisp, но даже в этом случае он шел медленно, и огромная проблема - это трудная трудность, которую я часто встречал при попытке исследовать внутреннюю работу объектов/типов/классов/и т.д. используя Scala REPL по сравнению с Python. В Python вы можете исследовать любой объект foo
(тип, объект в глобальной переменной, встроенная функция и т.д.), Используя foo
, чтобы узнать, что оценивается вещью, type(foo)
, чтобы показать его тип, dir(foo)
чтобы указать вам методы, которые вы можете вызвать, и help(foo)
, чтобы получить встроенную документацию. Вы можете даже делать такие вещи, как help("re")
, чтобы узнать документацию в пакете с именем re
(который содержит объекты и методы регулярного выражения), даже если нет связанного с ним объекта.
В Scala вы можете попробовать и прочитать документацию в Интернете, найти исходный код в библиотеке и т.д., но это часто может быть очень сложно для вещей, где вы не знаете, где и даже что они (и часто это большой кусок, чтобы откусить, учитывая иерархию объемного типа) - материал разворачивается в разных местах (пакет scala
, Predef
, различные неявные преобразования, символы типа ::
, которые почти невозможны гуглить). REPL должен быть способом непосредственного изучения, но на самом деле вещи гораздо более загадочны. Скажите, что я где-то видел ссылку на foo
, но я понятия не имею, что это такое. По-видимому, нет такой вещи, как "руководство по систематическому исследованию" w60 > штучек с REPL ", но следующее, что я собрал вместе после большого количества проб и ошибок:
- Если
foo
- это значение (которое предположительно включает в себя вещи, хранящиеся в переменных плюс сопутствующие объекты и другие Scalaobject
s), вы можете оценитьfoo
напрямую. Это должно указывать тип и ценность результата. Иногда результат полезен, иногда нет. - Если
foo
- значение, вы можете использовать:type foo
, чтобы получить его тип. (Не обязательно просвещать.) Если вы используете это при вызове функции, вы получаете тип возвращаемого значения, не вызывая функцию. - Если
foo
- значение, вы можете использоватьfoo.getClass
для получения своего класса. (Часто более просветляющий, чем предыдущий, но как класс объекта отличается от его типа?) - Для класса
foo
вы можете использоватьclassOf[foo]
, хотя это не очевидно, что означает результат. - Теоретически вы можете использовать
:javap foo
, чтобы разобрать класс, который должен быть самым полезным из всех, но полностью и единообразно для меня. - Иногда вам приходится собирать вещи из сообщений об ошибках.
Пример отказа с использованием :javap
:
scala> :javap List
Failed: Could not find class bytes for 'List'
Пример сообщения об ошибке просвещения:
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
^
ОК, теперь попробуйте простой пример.
scala> 5
res63: Int = 5
scala> :type 5
Int
scala> 5.getClass
res64: java.lang.Class[Int] = int
Достаточно просто...
Теперь попробуем несколько реальных случаев, где это не так очевидно:
scala> Predef
res65: type = [email protected]
scala> :type Predef
type
scala> Predef.getClass
res66: java.lang.Class[_ <: object Predef] = class scala.Predef$
Что это значит? Почему тип Predef
просто type
, тогда как класс scala.Predef$
? Я понимаю, что $- способ, с помощью которого сопутствующие объекты перекодированы в Java... но Scala docs в Google говорят мне, что Predef
is object Predef extends LowPriorityImplicits
- как я могу это сделать из REPL? И как я могу посмотреть, что в нем?
Хорошо, попробуй еще одну запутанную вещь:
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
ОК, это оставило меня безнадежно запутанным, и в итоге мне пришлось читать исходный код, чтобы понять все это.
Итак, мои вопросы:
- Каким рекомендуемым лучшим способом от истинных экспертов Scala использовать REPL, чтобы осмыслить объекты, классы, методы и т.д. w60, или, по крайней мере, исследовать их как можно лучше, чем это сделать из REPL?
- Как мне получить
:javap
работу с REPL для встроенных файлов? (Не работает ли он по умолчанию?)
Спасибо за любое просвещение.