Scala の記号演算子はどのような意味を持つのでしょうか? 質問する

Scala の記号演算子はどのような意味を持つのでしょうか? 質問する

Scala 構文には多くの記号があります。これらの種類の名前は検索エンジンで見つけるのが難しいため、包括的なリストがあると便利です。

Scala のすべてのシンボルとは何ですか? また、それぞれのシンボルはどのような機能を果たしますか?

特に->、、、、、、、および||=について知りたいです。++=<=_._:::+=

ベストアンサー1

私は、教育の目的で、演算子を4 つのカテゴリに分類します。

  • キーワード/予約記号
  • 自動的にインポートされたメソッド
  • 一般的な方法
  • 構文糖/構成

幸いなことに、ほとんどのカテゴリがこの質問に含まれています。

->    // Automatically imported method
||=   // Syntactic sugar
++=   // Syntactic sugar/composition or common method
<=    // Common method
_._   // Typo, though it's probably based on Keyword/composition
::    // Common method
:+=   // Common method

これらのメソッドのほとんどの正確な意味は、それを定義しているクラスによって異なります。たとえば、<=「以下」Intを意味します。最初の を以下に例として示します。はおそらく で定義されたメソッドであり(同じ名前のオブジェクトである可能性もありますが)、はおそらくさまざまなクラスで定義されたメソッドです。->::List:+=Buffer

それでは、見てみましょう。

キーワード/予約記号

Scala には特別なシンボルがいくつかあります。そのうち 2 つは適切なキーワードとみなされ、他のシンボルは単に「予約済み」です。特別なシンボルは次のとおりです。

// Keywords
<-  // Used on for-comprehensions, to separate pattern from generator
=>  // Used for function types, function literals and import renaming

// Reserved
( )        // Delimit expressions and parameters
[ ]        // Delimit type parameters
{ }        // Delimit blocks
.          // Method call and path separator
// /* */   // Comments
#          // Used in type notations
:          // Type ascription or context bounds
<: >: <%   // Upper, lower and view bounds
<? <!      // Start token for various XML elements
" """      // Strings
'          // Indicate symbols and characters
@          // Annotations and variable binding on pattern matching
`          // Denote constant or enable arbitrary identifiers
,          // Parameter separator
;          // Statement separator
_*         // vararg expansion
_          // Many different meanings

これらはすべて言語の一部であり、言語を適切に説明するあらゆるテキストに含まれています。たとえば、Scala仕様(PDF) 自体。

最後のアンダースコアは、非常に広く使用されており、さまざまな意味を持つため、特別な説明が必要です。次に例を示します。

import scala._    // Wild card -- all of Scala is imported
import scala.{ Predef => _, _ } // Exception, everything except Predef
def f[M[_]]       // Higher kinded type parameter
def f(m: M[_])    // Existential type
_ + _             // Anonymous function placeholder parameter
m _               // Eta expansion of method into method value
m(_)              // Partial function application
_ => 5            // Discarded parameter
case _ =>         // Wild card pattern -- matches anything
f(xs: _*)         // Sequence xs is passed as multiple parameters to f(ys: T*)
case Seq(xs @ _*) // Identifier xs is bound to the whole matched sequence

たぶん他の意味を忘れてしまったのでしょう。

自動的にインポートされたメソッド

したがって、上記のリストで探しているシンボルが見つからない場合、それはメソッド、またはメソッドの一部であるはずです。ただし、多くの場合、シンボルが表示されても、クラスのドキュメントにそのメソッドは記載されていません。このような場合は、1 つ以上のメソッドと他のメソッドの組み合わせを見ているか、メソッドがスコープにインポートされているか、インポートされた暗黙的な変換を通じて使用可能になっています。

これらはまだ見つかりますスカラドキュメント: どこで探すかを知るだけでいいのです。それができない場合は、索引(現在 2.9.1 では壊れていますが、nightly では利用可能です)。

すべての Scala コードには 3 つの自動インポートがあります。

// Not necessarily in this order
import _root_.java.lang._      // _root_ denotes an absolute path
import _root_.scala._
import _root_.scala.Predef._

最初の2つはクラスとシングルトンオブジェクトのみを利用可能にします。3つ目はすべての暗黙的な変換とインポートされたメソッドを含みます。Predefそれ自体がオブジェクトです。

内部をPredefざっと見てみると、いくつかのシンボルが示されています:

class <:<
class =:=
object <%<
object =:=

その他のシンボルは、暗黙的な変換を通じて使用可能になります。そのタグが付けられたメソッドを見るとimplicit、メソッドを受け取る型のオブジェクトがパラメータとして受け取られます。例:

"a" -> 1  // Look for an implicit from String, AnyRef, Any or type parameter

上記の場合、->クラスで定義されていますArrowAssocany2ArrowAssoc型のオブジェクトを受け取るメソッドを通じてAA同じメソッドへの無制限の型パラメータが渡されます。

一般的な方法

つまり、多くのシンボルは単にクラスのメソッドです。例えば、

List(1, 2) ++ List(3, 4)

この方法は++ScalaDocで見つけることができます。リストただし、メソッドを検索するときに注意しなければならない規則が 1 つあります。コロン ( :)で終わるメソッドは、左ではなく右にバインドされます。つまり、上記のメソッド呼び出しは次のものと同等です。

List(1, 2).++(List(3, 4))

代わりに、次のようにすると1 :: List(2, 3)、次のようになります。

List(2, 3).::(1)

したがって、コロンで終わるメソッドを探すときは、右側にある型を確認する必要があります。たとえば、次のようになります。

1 +: List(2, 3) :+ 4

最初のメソッド ( +:) は右にバインドし、 にありますList。2 番目のメソッド ( :+) は通常のメソッドであり、 の左にバインドします (これも ) List

構文糖/構成

したがって、メソッドを非表示にする可能性のある構文糖衣をいくつか示します。

class Example(arr: Array[Int] = Array.fill(5)(0)) {
  def apply(n: Int) = arr(n)
  def update(n: Int, v: Int) = arr(n) = v
  def a = arr(0); def a_=(v: Int) = arr(0) = v
  def b = arr(1); def b_=(v: Int) = arr(1) = v
  def c = arr(2); def c_=(v: Int) = arr(2) = v
  def d = arr(3); def d_=(v: Int) = arr(3) = v
  def e = arr(4); def e_=(v: Int) = arr(4) = v
  def +(v: Int) = new Example(arr map (_ + v))
  def unapply(n: Int) = if (arr.indices contains n) Some(arr(n)) else None
}

val Ex = new Example // or var for the last example
println(Ex(0))  // calls apply(0)
Ex(0) = 2       // calls update(0, 2)
Ex.b = 3        // calls b_=(3)
// This requires Ex to be a "val"
val Ex(c) = 2   // calls unapply(2) and assigns result to c
// This requires Ex to be a "var"
Ex += 1         // substituted for Ex = Ex + 1

最後のものは興味深いもので、任意のシンボリックメソッドを組み合わせて、割り当てのようなメソッドを形成できるからです。

もちろん、コードにはさまざまな組み合わせが出現します。

(_+_) // An expression, or parameter, that is an anonymous function with
      // two parameters, used exactly where the underscores appear, and
      // which calls the "+" method on the first parameter passing the
      // second parameter as argument.

おすすめ記事