2011-07-02 17 views
38

REPLでは、私は関数を定義します。戻り値の型に注意してください。スカラ文字列vs java.lang.String型推論

scala> def next(i: List[String]) = i.map {"0" + _} ::: i.reverse.map {"1" + _} 
next: (i: List[String])List[java.lang.String] 

そして、私は文字列

scala> def next(i: List[String]): List[String] = i.map {"0" + _} ::: i.reverse.map {"1" + _} 
next: (i: List[String])List[String] 

として戻り値の型を指定した場合、なぜ違いは?戻り値の型をList [Any]として指定することもできるので、Stringはjava.lang.Stringのラッパースーパータイプに過ぎないと思います。これには実際的な意味がありますか、返される型を安全に指定できませんか?

答えて

52

これは非常に良い質問です!まず、戻り値の型を安全に指定できることを保証します。

今、それを見てみましょう...はい、推測に残されたとき、スカラはStringの代わりにjava.lang.Stringを推定します。したがって、ScalaDocの "String"を検索すると、何も見つかりません。これはScalaクラスでもないことを示しているようです。まあ、それはどこかから来なければならない。

デフォルトでScalaがインポートするものを考えてみましょう。あなたはREPLに自分でそれを見つけることができます。

scala> :imports 
1) import java.lang._    (155 types, 160 terms) 
2) import scala._     (801 types, 809 terms) 
3) import scala.Predef._   (16 types, 167 terms, 96 are implicit) 

最初の二つは、パッケージされている - と、確かに、Stringjava.lang上で見つけることができます!そうですか?そのパッケージから別のインスタンスをインスタンス化して確認してみましょう:

scala> val s: StringBuffer = new StringBuffer 
s: java.lang.StringBuffer = 

scala> val s: String = new String 
s: String = "" 

それはそうではありません。今度は、scalaパッケージ内にあることはできません。あるいは、ScalaDocを参照するときに見つかったはずです。それではscala.Predefを見てみましょう! Stringは(以前にインポートされた)java.lang.Stringため別名であることを意味

type String = String 

。それはしかし循環参照のように見えますが、あなたはsourceをチェックすると、あなたはそれが完全なパスで定義されて表示されます:

type String  = java.lang.String 

次は、理由をお聞きしたいのでしょうか?まあ、私は何も考えていませんが、私はそれほど重要なクラスをJVMにあまり依存しないようにすることが考えられます。

+0

文字列リテラルがjava.lang.String型であると推測されるのはちょっと奇妙ですが、文字列型であるとも推測できます。しかし、彼らがまったく同じことを知ってうれしいです。 –

+0

@Luigiこれは、リテラルがjava.lang.String型であるためです。実際には推論はありません。リテラルです。 –

+2

おそらく私が今までに見た中で最も明快で、最高の、よく意図された答えです。とても爽やかです。ありがとうダニエル – jbnunn

関連する問題