我一直在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