73

数学とコンピューター サイエンスでは、タプルは要素の順序付きリストです。集合論では、(順序付き) n-タプルは n 要素のシーケンス (または順序付きリスト) であり、n は正の整数です。

したがって、たとえば Python では、タプルの 2 番目の項目は を介し​​てアクセスされますt[1]

Scala では、奇妙な名前を介してのみアクセスが可能t._2です。

問題は、タプルのデータにシーケンスまたはリストとしてアクセスできないのはなぜですか? ある種のアイデアがありますか、それともまだ検査されていませんか?

4

8 に答える 8

93

Scala はタプルのアリティを認識しているため_1、 、 などのアクセサーを提供できます。たとえば、ペア_2を選択すると、コンパイル時にエラーが発生します。_3さらに、これらのフィールドの型は、パラメーターとして使用される型とまったく同じですTuple(たとえば_3、 a は aTuple3[Int, Double, Float]を返しますFloat)。

n 番目の要素にアクセスしたい場合は と記述できますがtuple.productElement(n)、これの戻り値の型は しかないAnyため、型情報が失われます。

于 2011-07-30T16:09:07.430 に答える
39

「Scalaでのプログラミング:包括的なステップバイステップガイド」(Martin Odersky、Lex Spoon、Bill Venners)からの次の抜粋は、両方の質問に直接対応していると思います。

タプルの要素へのアクセス

たとえば、「pair(0)」を使用して、リストの要素のようなタプルの要素にアクセスできないのはなぜか疑問に思われるかもしれません。その理由は、リストのapplyメソッドは常に同じタイプを返しますが、タプルの各要素は異なるタイプである可能性があるためです。_1は1つの結果タイプ、_2は別の結果タイプなどになります。これらの_N番号は、ゼロベースではなく1ベースです。これは、1から始まるのは、HaskellやMLなどの静的に型付けされたタプルを持つ他の言語によって設定された伝統だからです。

Scalaタプルは、コンパイラによってscala.Tuplen( a1、...、)クラスのインスタンス化'(' a1, ..., an ')'のエイリアスとして扱われる式を除いて、言語構文に関する限り、ほとんど優先的に扱われません。それ以外の場合、タプルは他のScalaオブジェクトと同じように動作します。実際、タプルは、Tuple2からTuple22の範囲のケースクラスとしてScalaで記述されています。Tuple2とTuple3は、それぞれペアとトリプルのエイリアスでも知られています。

 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)
于 2011-11-26T01:59:01.257 に答える
20

List、または任意のコレクションとタプルの大きな違いの 1 つSeqは、タプルでは各要素に独自の型があるのに対し、リストではすべての要素が同じ型を持つことです。

Tuple2[T1, T2]結果として、Scala ではorのようなクラスが見つかるTuple3[T1, T2, T3]ため、各要素には型パラメーターもあります。コレクションは 1 つの型パラメーターのみを受け入れます: List[T]. Syntax like("Test", 123, new Date)は、 の構文糖衣にすぎませんTuple3[String, Int, Date]。、などは_1_2対応する要素を返すタプルの単なるフィールドです。

于 2011-07-30T16:10:17.960 に答える
12

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

標準コレクションで使用できる多くのメソッドは、このようにタプルでも使用できます ( headtailinitlast、連結、++要素の追加、、、、、、、... ):::+::+takedropreversezipunziplengthtoListtoArrayto[Collection]

于 2014-07-19T01:49:09.700 に答える
8

タイプチェック用だと思います。delnan が言うように、タプルtとインデックスe(任意の式)t(e)がある場合、どの要素がアクセスされているか (または、そのサイズのタプルに対して有効な要素であっても) に関する情報がコンパイラに提供されません。フィールド名 (_2は有効な識別子であり、特別な構文ではありません) で要素にアクセスすると、コンパイラはアクセスしているフィールドとその型を認識します。Python のような言語には実際には型がないため、これは必要ありません。

于 2011-07-30T16:09:11.327 に答える
7

通常のインデックス アクセスでは、任意の式を使用できます。インデックス式の結果が範囲内にあることが保証されているかどうかをコンパイル時にチェックするには、かなりの労力が必要です。それを属性にすると、コンパイル時エラーが(1, 2)._3「無料で」続きます。タプルの項目アクセス内で整数定数のみを許可するようなことは、非常に特殊なケース (醜くて不要で、ばかげていると言う人もいます) であり、コンパイラで実装する作業もあります。

たとえば、Pythonは、とにかくインデックスが範囲内にあるかどうかを(コンパイル時に)チェックしない(できない)ため、それを回避できます。

于 2011-07-30T16:03:34.690 に答える
0

Jean-Philippe Pellet がすでに述べた利点とは別に、この表記法は数学でも非常に一般的です ( http://en.wikipedia.org/wiki/Tupleを参照)。多くの講師は、タプルの要素を参照したい場合、タプル変数にインデックスを追加します。また、「with index n 」(タプルのn番目の要素を指す) を記述するための一般的な (LaTeX) 表記は です_n。ですから、実際には非常に直感的だと思います。

于 2014-07-21T11:54:27.537 に答える