我一直在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
,各种隐式转换,像Google几乎不可能的::
等符号)。 REPL应该是直接探索的方式,但事实上,事情更加神秘。假设我在某处看过foo
的引用,但我不知道它是什么。有显然是一个没有这样的事情“指南,系统地调查斯卡拉一样的东西与REPL”,但下面是试错大量后我所拼凑起来:如何调查对象/类型/等。来自Scala 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中的方式......但Google上的斯卡拉文档告诉我Predef
是object Predef extends LowPriorityImplicits
- 我怎样才能从REPL中推断出这一点?我怎样才能看看它里面有什么?
OK,让我们尝试另一个令人困惑的事情:
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,这让我绝望迷茫,最终,我不得不去阅读源代码,以使这个意义上说所有。
所以,我的问题是:
- 什么是从使用REPL有道理的Scala的对象,类,方法等的真实斯卡拉专家建议最好的办法,或者至少调查他们作为可以从REPL做到最好?
- 我如何从REPL获取
:javap
的内置内容? (默认情况下不应该工作吗?)
感谢您的任何启示。
感谢一个了不起的写了!我还会提到在M4发布后不久添加的“showRaw”(明天将出现在M5中)。它让我们检查一些反射工件(包括树和类型)的内部结构。 – 2012-07-09 13:29:19
@EugeneBurmako:我知道'universe.showRaw'是M4的成员之一,你的意思是另一个'showRaw'? – sschaef 2012-07-09 14:33:41
是的,我正在谈论这个。在M4发布后的几天内,它被重新修改。 – 2012-07-09 16:17:00