2015-10-12 7 views
10

私はスカラ座に新しいですし、私はこのようなScalaで文字列を連結するためのコードを見ている文字列「+」 Scala Docスカラ:VS「++」

"test " + "1" 

だから私の理解では、+は、JavaのString +のようなものですが、++は、パラメータのより多くの種類に取ることができ、より強力であるということです。また++はListのような他のものに普遍的なようです。私の理解が正しいかどうかを知りたい。その他の違いは?文字列の連結のためには、いつ別のものを使うべきですか?

+0

、私はもはや '+'使用しないことをお勧めします。おそらく廃止され、最終的に削除されます。スカラには文字列を補間する方法があります。 '++'を使うことは遅くなるかもしれませんが、私はそれが構文上明確で、Scalaのコレクションと一線を画した良い選択肢だと思います。 –

+0

@ 0__ 2時間前、+はJava文字列の権利ですか?その場合、ScalaはScala文字列を保持していますか? –

+0

'+'は 'java.lang.String' APIで定義されていません。Javaでは文字列ビルダーを実行するための単なる構文糖です。これはScalaでも同じです。ここでは 'Predef.any2stringadd'がなくても' + 'を使ったStringカテネーションがコンパイラによって定義されています。以下も参照してください:https://stackoverflow.com/questions/2664274/how-to-unimport-string-operator-in-scala –

答えて

10

は、それは正確に何が起こっているかを確認するためにscala.Predefで見てみるのに役立ちます。

スカラのStringjava.lang.Stringのエイリアスにすぎないことがわかります。換言すれば、String+メソッドは、Javaの+演算子に変換されます。

Scala StringがちょうどJava Stringの場合、++メソッドはどのように存在するのでしょうか。答えは、少なくともにあるwrapStringメソッドによって提供されるStringからWrappedStringへの暗黙的な変換があるということです。

++GenTraversableOnceのインスタンスをすべて取り、そのインスタンスのすべての要素を元のWrappedStringに追加します。 (ドキュメントにはWrappedString[B]が返されていることが間違っていることに注意してください。WrappedStringはタイプパラメータを取らないため、これは間違っています)。返すものはStringです(追加するものがSeq[Char]の場合)またはIndexedSeq[Any](そうでない場合)です。ここで

は、いくつかの例は以下のとおりです。

あなたはList[Char]Stringを追加する場合は、文字列を取得します。

scala> "a" ++ List('b', 'c', 'd') 
res0: String = abcd 

あなたはList[String]Stringを追加する場合は、IndexedSeq[Any]を取得します。実際、最初の2つの要素はCharですが、後の3つはStringです(フォローアップコールが示すように)。あなたはString++Stringに追加した場合

scala> "ab" ++ List("c", "d", "e") 
res0: scala.collection.immutable.IndexedSeq[Any] = Vector(a, b, c, d, e) 

scala> res0 map ((x: Any) => x.getClass.getSimpleName) 
res1: scala.collection.immutable.IndexedSeq[String] = Vector(Character, Character, String, String, String) 

最後に、あなたが戻ってString得ます。この理由は、WrappedString継承IndexedSeq[Char]から、ので、これはバックSeq[Char]あなたを与えるSeq[Char]Seq[Char]を追加する複雑な方法であるということです。

scala> "abc" + "def" 
res0: String = abcdef 

アレクセイが指摘したように、これらのいずれも非常に微妙なツールであり、そうでないと十分な理由がありますしない限り、あなたはおそらくstring interpolationまたはStringBuilderを使用して方がいいでしょう。

2

だから私の理解では、+は、JavaのString +のようなものですが、より強力++で、事があるパラメータ

より多くの種類の中で取ることができ、文字列の+が、この中でより強力であるということですsense:Javaの場合と全く同様に、パラメータを取ることができます。これはしばしば間違っていると考えられます(特に右の文字列でも機能するため)。 ++は、あなたが言うように、一般的なコレクションメソッドであり、より多くの型セーフ("test " ++ 1はコンパイルされません)です。

いつ文字列連結のために1つずつ上書きする必要がありますか?

私は+が好きです。しかし、多くの人にとって(私はほとんどを言うだろうが)あなたが望むものはどちらでもない:代わりにstring interpolationを使用してください。

val n = 1 
s"test $n" 

そして多くのの部分から文字列を構築するときはもちろん、StringBuilderを使用します。

+0

"+"はより強力ですが、私はその暗黙の変換を文字列へのintはJavaの権利で起こった? –

+0

厳密に言えば、暗黙の変換は必要ありません。 Javaでは、いわゆる[文字列変換](https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.18.1)があります。 Scalaの 'String'は' def +(other:Any) 'メソッドを持っているとみなされるので、引数をとることができます。暗黙の変換は、適切な '+'メソッドのない '' String''値が左側にあり、右側の '' String''( '' any2stringAdd'(http://www.scala-lang.org/ api/current/index.html#scala.Predef $$ any2stringadd))、この場合はScalaで発生します。 –

0

++は、必ずしも「より強力」であるとは限りませんが、通常、連結/追加操作として使用されます。ただし、割り当ては実行されません。 IE listX ++ yはlistXに追加されますが、i++は整数iをインクリメントしません(これは変数と代入を代入するためです)。

これは少なくとも私の理解です。私はScalaの専門家ではありません。

0

StringからStringOpsへの暗黙的な変換がscala.Predefにあります。 ++メソッドはStringOpsクラスで定義されています。したがって、いつでも、str1 ++ str2を実行するたびに、スケーラコンパイラは、StringOpsstr1をラップし、というメソッドを呼び出すことが本質的に(コーダの観点から)です。 StringOpsは本質的にIndexedSeqのソートなので、++演算子は非常に柔軟です。

"Hello, " ++ "world!" //results in "Hello, world" with type String 
"three" ++ (1 to 3) //results in Vector('t', 'h', 'r', 'e', 'e', 1, 2, 3) with type IndexedSeq[AnyVal] 
3

Stringは、TraversableLikeです。つまり、要素(文字)のシーケンスに分解することができます。それは++から来ています。そうでなければ、++をStringにできません。ときの右側(またはその関数へのパラメータ)++のみ機能するであろう、デ構成可能型(又はトラバース)です。

今どのようStringTraversableLikeになるのでしょうか?これは、Predefで定義された暗黙のうちに現れます。>TraversableLike

- - > StringBuilder - > StringLike - > IndexedSeqOptimized - > IndexedSeqLike - > SeqLike - > IterableLike

WrappedString.canBuildFrom:暗黙的の一つは、WrappedString.canBuildFromは基本的に、このように動作するすべての接着剤を持っているWrappedStringString通常の変換します

Predefで定義された暗黙のスコープに既にあるので、このようなコードを記述することが可能である:今、あなたの質問に

"test " ++ "1" 

を:

私の理解が正しいかどうかを知りたい。その他の違いは?

はいあなたの理解は正しい方向です。

いつ文字列連結のために1つずつ上書きする必要がありますか?

文字列連結の場合、明らかに"test " + "1"は少ないオブジェクトを生成し、関数呼び出しの数は少なくなります。しかし、私は常に以下のような文字列補間を好むでしょう:

val t1 = "test" 
val t2 = "1" 
val t3 = s"$t1 $t2" 

これは読みやすいです。

詳細については