Я работаю с 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- это значение (которое предположительно включает в себя вещи, хранящиеся в переменных плюс сопутствующие объекты и другие Scalaobjects), вы можете оценить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 для встроенных файлов? (Не работает ли он по умолчанию?)
Спасибо за любое просвещение.