「タプル」の版間の差分
m 2405:6580:D220:7900:158B:F12C:9C1C:12BA (会話) による ID:77696298 の版を取り消し タグ: 取り消し |
|||
61行目: | 61行目: | ||
===Lispの場合=== |
===Lispの場合=== |
||
(伝統的な)[[Lisp]]の場合、基本的には線型リストを作るためのデータ構造であるコンスセル(cons cell)を、要素2個のタプル(二ツ組)に流用する。[[Cons (Lisp)|cons]], [[CARとCDR|car, cdr]] というリスト操作用の関数もそのまま流用される。格納するデータの型に制限はない。 |
(伝統的な)[[Lisp]]の場合、基本的には線型リストを作るためのデータ構造であるコンスセル(cons cell)を、要素2個のタプル(二ツ組)に流用する。[[Cons (Lisp)|cons]], [[CARとCDR|car, cdr]] というリスト操作用の関数もそのまま流用される。格納するデータの型に制限はない。 |
||
< |
<syntaxhighlight lang="lisp"> |
||
(cons car部のデータ cdrのデータ) |
(cons car部のデータ cdrのデータ) |
||
</syntaxhighlight> |
|||
</source> |
|||
{{lang|en|car}}部のデータを取り出すには関数 <code>car</code> を使い、{{lang|en|cdr}}部のデータを取り出すには関数 <code>cdr</code> を使う。 |
{{lang|en|car}}部のデータを取り出すには関数 <code>car</code> を使い、{{lang|en|cdr}}部のデータを取り出すには関数 <code>cdr</code> を使う。 |
||
< |
<syntaxhighlight lang="lisp"> |
||
(setq x (cons 'A 1)) |
(setq x (cons 'A 1)) |
||
(setq a (car x)) ; a には 'A が入る |
(setq a (car x)) ; a には 'A が入る |
||
(setq b (cdr x)) ; b には 1 が入る |
(setq b (cdr x)) ; b には 1 が入る |
||
</syntaxhighlight> |
|||
</source> |
|||
また、 |
また、 |
||
< |
<syntaxhighlight lang="lisp"> |
||
(list データ1 データ2 データ3 … データN) |
(list データ1 データ2 データ3 … データN) |
||
</syntaxhighlight> |
|||
</source> |
|||
という関数呼び出しは、 |
という関数呼び出しは、 |
||
< |
<syntaxhighlight lang="lisp"> |
||
(cons データ1 (cons データ2 (cons データ3 … (cons データN nil) … ))) |
(cons データ1 (cons データ2 (cons データ3 … (cons データN nil) … ))) |
||
</syntaxhighlight> |
|||
</source> |
|||
という形、すなわち、{{lang|en|car}}部にデータがあり、{{lang|en|cdr}}部が後続のコンスセルになっており、最後の{{lang|en|cdr}}部分を <code>nil</code> という特殊な記号で終端させた二分木を返す。このような形式の二分木は「ちゃんとした」リストになっていると言えることから、「(プロパー)リスト」などという。 |
という形、すなわち、{{lang|en|car}}部にデータがあり、{{lang|en|cdr}}部が後続のコンスセルになっており、最後の{{lang|en|cdr}}部分を <code>nil</code> という特殊な記号で終端させた二分木を返す。このような形式の二分木は「ちゃんとした」リストになっていると言えることから、「(プロパー)リスト」などという。 |
||
161行目: | 161行目: | ||
{{lang|en|[[C Sharp|C#]]}}言語におけるタプル(<code>System.Tuple</code>クラス)は[[.NET Framework]] 4.0からサポートされた[[総称型]]の[[コンテナ (データ型)|コンテナ]]のひとつ。[[共通言語基盤|CLI]]で定義されたクラスであるため[[Visual Basic .NET]]でも同様に使用可能である。 |
{{lang|en|[[C Sharp|C#]]}}言語におけるタプル(<code>System.Tuple</code>クラス)は[[.NET Framework]] 4.0からサポートされた[[総称型]]の[[コンテナ (データ型)|コンテナ]]のひとつ。[[共通言語基盤|CLI]]で定義されたクラスであるため[[Visual Basic .NET]]でも同様に使用可能である。 |
||
< |
<syntaxhighlight lang="csharp"> |
||
var tuple1 = new Tuple<int>(1); |
var tuple1 = new Tuple<int>(1); |
||
var tuple2 = new Tuple<string, int>("one", 1); |
var tuple2 = new Tuple<string, int>("one", 1); |
||
</syntaxhighlight> |
|||
</source> |
|||
それぞれの値の取り出しは、<code>Item1</code>, <code>Item2</code>, ... にアクセスすることで行える。{{lang|en|Python}}と違い、Tuple型で返したからといって複数の戻り値を返す関数とはならない。 |
それぞれの値の取り出しは、<code>Item1</code>, <code>Item2</code>, ... にアクセスすることで行える。{{lang|en|Python}}と違い、Tuple型で返したからといって複数の戻り値を返す関数とはならない。 |
||
< |
<syntaxhighlight lang="csharp"> |
||
var tuple2 = new Tuple<string, int>("one", 1); |
var tuple2 = new Tuple<string, int>("one", 1); |
||
string word = tuple2.Item1; |
string word = tuple2.Item1; |
||
int number = tuple2.Item2; |
int number = tuple2.Item2; |
||
</syntaxhighlight> |
|||
</source> |
|||
他にも同様の総称型を持つ言語では、同様にしてタプルを使える<ref>例えば[[C++11]]のタプル型</ref>かもしれない。 |
他にも同様の総称型を持つ言語では、同様にしてタプルを使える<ref>例えば[[C++11]]のタプル型</ref>かもしれない。 |
||
180行目: | 180行目: | ||
タプル構文では<code>System.ValueTuple</code>構造体が使用される。 |
タプル構文では<code>System.ValueTuple</code>構造体が使用される。 |
||
< |
<syntaxhighlight lang="csharp"> |
||
// 名前なしタプル |
// 名前なしタプル |
||
var tuple1 = ("one", 1); |
var tuple1 = ("one", 1); |
||
191行目: | 191行目: | ||
// タプルの分解 |
// タプルの分解 |
||
(string str, int num) = tuple1; |
(string str, int num) = tuple1; |
||
</syntaxhighlight> |
|||
</source> |
|||
===TypeScript におけるタプル=== |
===TypeScript におけるタプル=== |
||
[[TypeScript]] 1.3 から対応した。 |
[[TypeScript]] 1.3 から対応した。 |
||
< |
<syntaxhighlight lang="javascript"> |
||
var tuple: [string, number] = ["one", 1]; |
var tuple: [string, number] = ["one", 1]; |
||
</syntaxhighlight> |
|||
</source> |
|||
===関係データベースにおけるタプル=== |
===関係データベースにおけるタプル=== |
2020年7月5日 (日) 22:42時点における版
タプルまたはチュープル(英: tuple)とは、複数の構成要素からなる組を総称する一般概念。
数学や計算機科学などでは通常、順序付けられた対象の並びを表すために用いられる。個別的には、n 個でできた組を英語で「n-tuple」と書き、日本語に訳す場合は通常「n 組」としている。タプルの概念そのものも組と呼ばれる場合がある。なお、 n-tuple は数学のタプルを意味するほか、同様に double、triple などの拡張として倍数詞の表現にも利用される(詳細は「倍#西洋数学における n 倍を表す表現」を参照)。
数学におけるタプル
集合論では n 組 (n-tuple) とは n 個の対象 a1, a2, ..., an の順序づけられた組であり、普通、括弧でくくって (a1, a2, a3, ..., an) のように書かれる。 タプルが順序づけられているということは、
- 「2つの n 組 (a1, a2, ..., an) と (b1, b2, ..., bn) が等しい」
- という表現の意味することが、
- 「対応する位置の要素がすべて等しいとき」
- すなわち
- 「 (a1 = b1) ∧ (a2 = b2) ∧ ... ∧ (an = bn) であるとき、かつそのときに限ること」
を意味する。 タプルと直積集合には密接な関係があり、n 組の i 番目の対象が集合 Ai の要素とみなされるならば、n 組は直積集合 A1 × A2 × ... × An の要素である。
2 つの要素 a ∈ A, b ∈ B の順序づけられた組 (a, b) ∈ A × B は特に順序対 (ordered pair) と呼ばれる。 形式上は逆に、この順序対を元とすることによって一般の n 組 (n ≧ 2) を、例えば (a1, a2, a3, ..., an) = (...((a1, a2), a3), ..., an) のようにして構成的に定めることもできる。
タプルは様々な数学概念を定義するためにも利用される。 例えば、有限オートマトンは、入力アルファベットの有限集合 Σ, 状態の有限集合 S, 初期状態 s0 ∈ S, 遷移関数 δ : Σ × S → S, 受理状態の有限集合 F ⊆ S の 5 つ組 (quintuple, 5-tuple) (Σ, S, s0, δ, F) として定められ、有向グラフは、頂点集合 V と辺の集合 A ⊆ V × V の順序対 (V, A) として定められる。
なお数ベクトルも同じように要素の順序づけられた並びとして表されるが、数学の形式上、ある線形空間の要素とみなされるベクトルは実数、複素数など同じ体の要素からなるものである。 対して、タプルは任意の集合の要素を並べただけのずっと一般的な概念であるといえる。
タプルの特殊名
タプルには要素の個数による特殊名が存在する。これらはフランス語に由来するラテン語系の語彙で、少なくとも「クインチュープル」までと「デキュプル」は輸入当時のフランス語から直接受け継いだものである。「 - チュープル」や「 - チュプル」となる個所を「 - タプル」と呼ぶこともある(クインタプル、セクスタプルなど)。また「クオドループル」は「カドラプル」や「クアドラプル」とも言う。
和訳して言うこともある。例としては「シングル」→「一重」「一つ組」、「ダブル」→「二重」「二つ組」、「カドラプル」→「四重」「四つ組」、「デカプル」→「十重」「十個組」など。「シングル」「ダブル」「トリプル」については呼び方がさらにあり、シングルは「独」、ダブルは「ペア」やその和訳である「対」、トリプルは「鼎」が充てられることもある。
要素の数 | 特殊名 | 英名 |
---|---|---|
1 | シングル | single |
2 | ダブル | double |
3 | トリプル | triple |
4 | クオドループル | quadruple |
5 | クインチュープル | quintuple |
6 | セクスチュープル | sextuple |
7 | セプチュプル | septuple |
8 | オクチュプル | octuple |
9 | ノニュプル | nonuple |
10 | デキュプル | decuple |
100 | センチュプル | centuple |
タプル型
型システム的には、代数的データ型でいう直積型そのものであり、C#、C++、Haskell、Kotlin、ML、Python、Scala、TypeScript といった多くのプログラミング言語にタプル型がある。いくつかは (x, y)
といったような構文でタプル型の値を直接記述できる。
動的な型付けを持つ言語では、コンテナ型を使うことで済まさせている場合もある。一方でPythonのように、長さを後から変えられないばかりでなく要素を変えることもできないというような、タプル専用のオブジェクトを用意している場合もある。
静的な型付けを持つ言語の場合、リスト型やコンテナ型の要素は、基本的になんらかの「同じ」型でなければならないので、それらの集積型をタプルの目的に流用することは不可能であり、そのためこの節の冒頭のようにタプルないし同等のものをサポートしていることが多い。
Lispの場合
(伝統的な)Lispの場合、基本的には線型リストを作るためのデータ構造であるコンスセル(cons cell)を、要素2個のタプル(二ツ組)に流用する。cons, car, cdr というリスト操作用の関数もそのまま流用される。格納するデータの型に制限はない。
(cons car部のデータ cdrのデータ)
car部のデータを取り出すには関数 car
を使い、cdr部のデータを取り出すには関数 cdr
を使う。
(setq x (cons 'A 1))
(setq a (car x)) ; a には 'A が入る
(setq b (cdr x)) ; b には 1 が入る
また、
(list データ1 データ2 データ3 … データN)
という関数呼び出しは、
(cons データ1 (cons データ2 (cons データ3 … (cons データN nil) … )))
という形、すなわち、car部にデータがあり、cdr部が後続のコンスセルになっており、最後のcdr部分を nil
という特殊な記号で終端させた二分木を返す。このような形式の二分木は「ちゃんとした」リストになっていると言えることから、「(プロパー)リスト」などという。
Python におけるタプル
Python におけるタプルは、任意の要素数の値をまとめてあたかもひとつの値のように扱う機能である。
タプルでは要素の型 (数値型、文字列型など)の同一性は不問であり、たとえば ('A', 1)
という文字列と整数をひと塊として変数に代入できる。
x = ('A', 1)
Pythonはゼロまたはひとつの要素となるタプルも認めており、とくに1要素のタプルはプログラミング言語としては珍しい。普通、そのようなものは計算の優先順位を変更するため、または1引数関数の引数を括るための括弧と区別できないからである。Pythonの場合、要素に続けてカンマを置くことで識別する。カンマを忘れるとタプルとして認識できなくなってしまうということでもある。
x = (1,) # 1要素の場合。()内末尾のカンマに注意
y = () # 0要素の場合。関数型言語ではユニットとして知られているが、タプルとは別に語られる
タプルは関数の返り値として使うこともできる。これによって、複数の値を返す関数を実現することができる。
def func():
return ('A', 1)
x = func() # x には ('A', 1) が入る
また、タプルは下記のようにして個別の要素を分離する。
x = ('A', 1)
(a, b) = x # a には 'A'、b には 1 が入る
Haskellにおけるタプル
ML系の関数型言語にほぼ共通して言えることとして、再帰的なデータ型であるリストとは異なり、タプルはそうでない点がある。また、リストの要素は単一の型のみを許容するのに対し、タプルの要素は型を問わない。これもデータ構造が再帰的か否かという点に由来するものである。また、要素へのアクセスはパターンマッチングか、先頭要素とその次の要素程度までを求める関数しかない。再帰的に定義されていないため、再帰関数で手繰ることも難しい(リストなら先頭と残りに分離することで容易に行える)。にもかかわらず、多くの関数型言語は60前後の要素まで許容されている。
Haskellでは、Pythonに類似した方法で利用できる部分もある。Pythonなどに影響を与えた側なので当然といえば当然である。
x = ('A', 1)
(a, b) = x -- a には 'A'、b には 1 が入る。パターンマッチの例
アクセス関数としては、第1要素を取得するfstと、第2要素を取得するsndがある。
x = ('A', 1)
a = fst x -- a には 'A' が入る
b = snd x -- b には 1 が入る
Haskellでは、2要素のタプルはデータ構築子 (,) で定義される。3要素なら (,,) で、最大の要素数は64であるため、これはカンマが63個並ぶことになる。以下はどちらも同じタプルが生成される。
x = ('A', 1)
y = (,) 'A' 1
もちろんセクション(演算子の部分適用)も可能である。
x = (, 'A')
f y = x -- y に1を与えたとすれば、fは (1, 'A') を返す
セクションなどでは、要素数に応じた構築子を使わなければならない。たとえば要素数が3ならば
f x y = (,,) x y 3
-- これは以下と等価である
f x y = (x, y, 3)
ユーティリティ関数としてcurryとuncurryが定義されている。いずれも2-tupleしか受け付けない。
curry id 'A' 1 -- id ('A', 1) と等価で、curryは ('A', 1) を返す
uncurry (+) (1,42) -- (+) 1 42 と等価で、これは 1 + 42 とも等価であるから、uncurryは43を返す
C# におけるタプル
C#言語におけるタプル(System.Tuple
クラス)は.NET Framework 4.0からサポートされた総称型のコンテナのひとつ。CLIで定義されたクラスであるためVisual Basic .NETでも同様に使用可能である。
var tuple1 = new Tuple<int>(1);
var tuple2 = new Tuple<string, int>("one", 1);
それぞれの値の取り出しは、Item1
, Item2
, ... にアクセスすることで行える。Pythonと違い、Tuple型で返したからといって複数の戻り値を返す関数とはならない。
var tuple2 = new Tuple<string, int>("one", 1);
string word = tuple2.Item1;
int number = tuple2.Item2;
他にも同様の総称型を持つ言語では、同様にしてタプルを使える[1]かもしれない。
C#7.0からサポートされたタプル構文では、より簡易な記法でタプルの取り扱いが可能となった。
また、分解構文をサポートしたため、多値戻り値が可能となった。
タプル構文ではSystem.ValueTuple
構造体が使用される。
// 名前なしタプル
var tuple1 = ("one", 1);
string word1 = tuple1.Item1;
int number1 = tuple1.Item2;
// 名前付きタプル
var tuple2 = (key: "one", value: 1);
string word2 = tuple2.key;
int number2 = tuple2.value;
// タプルの分解
(string str, int num) = tuple1;
TypeScript におけるタプル
TypeScript 1.3 から対応した。
var tuple: [string, number] = ["one", 1];
関係データベースにおけるタプル
関係データベースの理論である関係モデルでは、タプル(組)とはある関係(リレーション)を表(テーブル) として表したときの1つの行にあたり、形式的には、上述のタプルと同様に属性名を添字とした属性の型の直積集合の要素として表される。