Scalaでは、ケースクラスcase class Foo(x:Int)
を作成して、次のようにリストに入れることができます。
List(Foo(42))
ここで、奇妙なことは何もありません。以下は私には奇妙です。演算子::
はリストの関数ですよね? Scalaの引数が1つの関数であれば、中置記法で呼び出すことができます。たとえば、1 + 2
は、オブジェクトInt
に対する関数(+)
です。先ほど定義したクラスFoo
には::
演算子がないので、次のようにするにはどうすればよいですか?
Foo(40) :: List(Foo(2))
Scala 2.8 RC1で、インタラクティブプロンプトから次の出力を取得します。
scala> case class Foo(x:Int)
defined class Foo
scala> Foo(40) :: List(Foo(2))
res2: List[Foo] = List(Foo(40), Foo(2))
続けて使うことはできますが、その説明は?
仕様から:
6.12.3 InfixOperations infix演算子は任意の識別子にすることができます。中置演算子には、次のように定義された優先順位と結合規則があります。
...
演算子の関連性は、演算子の最後の文字によって決まります。コロン「:」で終わる演算子は右結合です。他のすべての演算子は左結合です。
Scala=)でこれらのルールがどのように適用されるかは、コンパイラの 'typer'フェーズを通過した後にプログラムを印刷することで常に確認できます。
scala -Xprint:typer -e "1 :: Nil"
val r: List[Int] = {
<synthetic> val x$1: Int = 1;
immutable.this.Nil.::[Int](x$1)
};
_:
_で終わります。そして、それは、この関数が右側のクラス(ここではList
クラス)で定義されていることを示しています。
したがって、例ではList(Foo(2)).::(Foo(40))
ではなくFoo(40).::(List(Foo(2)))
です。
指定された回答に欠けている1つの側面は、パターンマッチング式で_::
_をサポートすることです。
_List(1,2) match {
case x :: xs => println(x + " " + xs)
case _ => println("")
}
_
_final case class ::[B](private var hd: B, private[scala] var tl: List[B])
_
したがって、case ::(x,xs)
も同じ結果になります。式_case x :: xs
_が機能するのは、デフォルトの抽出子_::
_がケースクラスに定義されており、インフィックスで使用できるためです。
先ほど定義したクラス
Foo
には_::
_演算子がないため、次のようにすることができます。
Foo(40) :: List(Foo(2))
メソッド名がコロン(_:
_)で終わっている場合、メソッドは右側のオペランドで呼び出されます。メソッド名がコロンで終わらない場合、メソッドは左側のオペランドで呼び出されます。たとえば、_a + b
_、_+
_はa
で呼び出されます。
したがって、あなたの例では、_::
_はその右側のオペランドのメソッドであり、List
です。