私はしばらくの間 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 のことを体系的に調査するためのガイド」のようなものは明らかに存在しませんが、次のようなものがあります。
foo
が値 (おそらく、変数に格納されているものに加えて、コンパニオン オブジェクトやその他の Scala を含む) の場合は、直接object
評価できますfoo
。これにより、結果の型と値がわかります。結果が役立つ場合もあれば、そうでない場合もあります。foo
が値の場合、使用してその型を取得できます:type foo
。(必ずしも啓発的ではありません。) 関数呼び出しでこれを使用すると、関数を呼び出さずに戻り値の型を取得します。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
単に $ は、コンパニオン オブジェクトを Java に押し込む方法だと思いますが、Google の Scala ドキュメントでは、これはどうすれば REPL から推測できますか? そして、どうすればその内容を調べることができますか?type
scala.Predef$
Predef
object Predef extends LowPriorityImplicits
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 からできる限り最善の方法でそれらを調査するために、真の Scala の専門家が推奨する最良の方法は何ですか?
:javap
組み込みのものを REPL から操作するにはどうすればよいですか? (デフォルトで動作するはずではありませんか?)
啓発をありがとう。