我已经使用 Scala 有一段时间了,并用它编写了一个超过 10,000 行的程序,但我仍然对一些内部工作感到困惑。在已经非常熟悉 Java、C 和 Lisp 之后,我从 Python 来到了 Scala,但即便如此,它仍然进展缓慢,一个巨大的问题是我在尝试研究对象/类型的内部工作时经常发现令人沮丧的困难/类/等。与 Python 相比,使用 Scala REPL。在 Python 中,您可以调查任何对象foo
(类型、全局变量中的对象、内置函数等),foo
以查看事物的评估结果、type(foo)
显示其类型、dir(foo)
告诉您可以调用的方法,以及help(foo)
获取内置文档。你甚至可以做类似的事情help("re")
找出有关名为re
(包含正则表达式对象和方法)的包的文档,即使没有与之关联的对象。
在 Scala 中,您可以尝试在线阅读文档,查找库的源代码等,但这对于您不知道它们在哪里甚至是什么的事情通常非常困难(而且通常考虑到庞大的类型层次结构,一大块要咬掉)——东西在各个地方浮动(包scala
,,Predef
各种隐式转换,像::
这样的符号对谷歌来说几乎是不可能的)。REPL 应该是直接探索的方式,但实际上,事情要神秘得多。假设我在foo
某处看到了引用,但我不知道它是什么。显然没有“使用 REPL 系统地研究 Scala 事物的指南”这样的东西,但以下是我的
- 如果
foo
是一个值(大概包括存储在变量中的东西加上伴随对象和其他 Scalaobject
s),您可以直接评估foo
。这应该告诉您结果的类型和值。有时结果是有帮助的,有时没有。 - 如果
foo
是一个值,您可以使用:type foo
它来获取它的类型。(不一定有启发性。)如果您在函数调用中使用 this,您将获得返回值的类型,而无需调用该函数。 - 如果
foo
是一个值,您可以使用foo.getClass
它来获取它的类。(通常比前面的更有启发性,但是对象的类与其类型有何不同?) - 对于一个 class
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 = scala.Predef$@3cd41115
scala> :type Predef
type
scala> Predef.getClass
res66: java.lang.Class[_ <: object Predef] = class scala.Predef$
这是什么意思?为什么Predef
简单的类型是type
,而类是scala.Predef$
?我认为 $ 是伴随对象被硬塞到 Java 中的方式......但是 Google 上的 Scala 文档告诉我Predef
——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 来理解 Scala 对象、类、方法等的最佳方法是什么,或者至少可以从 REPL 中尽可能地研究它们?
- 我如何
:javap
从 REPL 获得内置的东西?(它不应该默认工作吗?)
感谢您的任何启发。