数学およびコンピューターサイエンスでは、タプルは要素の順序付きリストです。集合論では、(順序付けられた)n-タプルはn個の要素のシーケンス(または順序付きリスト)です。nは正の整数です。
したがって、たとえば、Pythonでは、タプルの2番目の項目にt[1]
経由でアクセスします。
Scalaでは、奇妙な名前t._2
を介してのみアクセスできます。
だから、質問は、定義によると、なぜシーケンスまたはリストとしてタプルのデータにアクセスできないのですか?何らかのアイデアがありますか、それともまだ検査されていませんか?
Scalaはタプルのアリティを知っているため、__1
_、__2
_などのアクセサを提供でき、ペアで__3
_を選択すると、コンパイル時エラーを生成できます。インスタンス。さらに、これらのフィールドのタイプは、Tuple
のパラメーターとして使用されているタイプとまったく同じです(たとえば、__3
_上の_Tuple3[Int, Double, Float]
_はFloat
を返します)。
N番目の要素にアクセスしたい場合は、Tuple.productElement(n)
を記述できますが、この戻り値の型はAny
のみであるため、型情報は失われます。
「Scalaでのプログラミング:包括的なステップバイステップガイド」(Martin Odersky、Lex Spoon、Bill Venners)からの次の抜粋は、両方の質問に直接対応していると思います。
タプルの要素へのアクセス
リストの要素のように、たとえば "pair(0)"でタプルの要素にアクセスできない理由を疑問に思うかもしれません。その理由は、リストのapplyメソッドは常に同じタイプを返しますが、Tupleの各要素は異なるタイプである可能性があるためです:_1は1つの結果タイプ、_2は別のタイプなどです。これらの_N番号は、0からではなく1から始まります。1から始まることは、HaskellやMLなどの静的に型付けされたタプルを使用する他の言語によって設定された伝統だからです。
Scalaタプルは、式'(' a1, ..., an ')'
以外の言語構文に関する限り、scala.Tuplen(a1、...、 an)クラスのインスタンス化。それ以外の場合、タプルは他のScalaオブジェクトと同様に動作し、実際にはScala as Tuple2からTuple22の範囲のクラスの場合 =。Tuple2とTuple3は、それぞれPairとTripleのエイリアスでも知られています。
val a = Pair (1,"two") // same as Tuple2 (1,"two") or (1,"two")
val b = Triple (1,"two",3.0) // same as Tuple3 (1,"two",3.0) or (1,"two",3.0)
List
、Seq
またはコレクションとTupleの大きな違いの1つは、Tupleでは各要素が独自の型を持ち、Listではすべての要素が同じ型を持つことです。
結果として、ScalaでTuple2[T1, T2]
やTuple3[T1, T2, T3]
のようなクラスが見つかるので、各要素にはtypeパラメーターもあります。コレクションは1つのtypeパラメーターのみを受け入れます:List[T]
。("Test", 123, new Date)
のような構文は、Tuple3[String, Int, Date]
の単なる構文上の砂糖です。また、_1
、_2
などは、対応する要素を返すTupleのフィールドにすぎません。
shapeless で簡単に実現できます:
import shapeless.syntax.std.Tuple._
val t = ("a", 2, true, 0.0)
val s = t(0) // String at compile time
val i = t(1) // Int at compile time
// etc
標準コレクションで利用可能な多くのメソッドは、この方法でタプルにも利用できます(head
、tail
、init
、last
、++
および:::
連結の場合、+:
および:+
要素を追加する場合、take
、drop
、reverse
、Zip
、unzip
、length
、toList
、toArray
、to[Collection]
、...)
型チェック用だと思います。 delnanが言うように、タプルt
とインデックスe
(任意の式)がある場合、t(e)
はコンパイラーにアクセスされている要素に関する情報を提供しません(または、そのサイズのタプルの有効な要素であっても)。フィールド名(_2
は有効な識別子であり、特別な構文ではありません)、コンパイラはアクセスしているフィールドとそのタイプを知っています。 Pythonのような言語は実際には型を持たないため、これは必要ありません。
通常のインデックスアクセスでは、任意の式を使用できます。また、インデックス式の結果が範囲内にあることが保証されているかどうかをコンパイル時に確認するには、かなりの努力が必要です。それを属性にすると、(1, 2)._3
のコンパイル時エラーが「無料」に続きます。タプルのアイテムアクセス内で整数定数のみを許可するようなものは非常に特殊なケースであり(ugくて不必要で、ばかげていると言う人もいます)、再びコンパイラに実装するためのいくつかの作業があります。
たとえばPythonは、インデックスが範囲内にあるかどうかを(コンパイル時に)チェックしない(できない)ため、それを回避できます。
Jean-Philippe Pelletが既に言及した利点とは別に、この表記は数学でも非常に一般的です( http://en.wikipedia.org/wiki/Tuple を参照)。多くの講師は、タプルの要素を参照したい場合、タプル変数にインデックスを追加します。 「インデックス付きn」を記述するための一般的な(LaTeX)表記法(タプルのn番目の要素を参照) _n
。だから、実際には非常に直感的だと思います。