タプル

"タプル" は、名前のない順序付けられた値のグループであり、型が異なる場合があります。 タプルは、参照型または構造体にすることができます。

構文

(element, ... , element)
struct(element, ... ,element )

解説

前の構文の各 "要素" は、任意の有効な F# 式にすることができます。

タプルの例としては、同じまたは異なる型の 2 つ組や 3 つ組などがあります。 いくつかの例を次のコードに示します。

(1, 2)

// Triple of strings.
("one", "two", "three")

// Tuple of generic types.
(a, b)

// Tuple that has mixed types.
("one", 1, 2.0)

// Tuple of integer expressions.
(a + 1, b + 1)

// Struct Tuple of floats
struct (1.025f, 1.5f)

個別の値の取得

次のコードに示すように、タプル要素にアクセスして名前を割り当てるためにパターン マッチングを使用できます。

let print tuple1 =
   match tuple1 with
    | (a, b) -> printfn "Pair %A %A" a b

また、let バインディングにより match 式の外側にあるパターン マッチングを使ってタプルを分解することもできます。

let (a, b) = (1, 2)

// Or as a struct
let struct (c, d) = struct (1, 2)

または、関数への入力としてタプルのパターン マッチングを行うことができます。

let getDistance ((x1,y1): float*float) ((x2,y2): float*float) =
    // Note the ability to work on individual elements
    (x1*x2 - y1*y2) 
    |> abs 
    |> sqrt

タプルの要素が 1 つだけ必要な場合は、不要な値に新しい名前が作成されないよう、ワイルドカード文字 (アンダースコア) を使用できます。

let (a, _) = (1, 2)

参照タプルから構造体タプルに要素をコピーすることも簡単です。

// Create a reference tuple
let (a, b) = (1, 2)

// Construct a struct tuple from it
let struct (c, d) = struct (a, b)

関数 fstsnd (参照タプルのみ) では、タプルの 1 番目と 2 番目の要素がそれぞれ返されます。

let c = fst (1, 2)
let d = snd (1, 2)

3 つ組の 3 番目の要素を返す組み込み関数はありませんが、次のように簡単に記述できます。

let third (_, _, c) = c

通常、個々のタプル要素にアクセスするには、パターン マッチングを使用することをお勧めします。

タプルの使用

タプルでは、次の例に示すように、関数から複数の値を返す便利な方法が提供されます。 この例では整数除算が実行され、演算の丸めた結果がタプルの 2 つ組の最初のメンバーとして、剰余が 2 つ組の 2 番目のメンバーとして返されます。

let divRem a b =
   let x = a / b
   let y = a % b
   (x, y)

通常の関数構文によって暗黙的に指定される関数の引数の暗黙的なカリー化を回避する場合は、関数の引数としてタプルを使用することもできます。

let sumNoCurry (a, b) = a + b

次のコードに示すように、この関数を定義するための通常の構文 let sum a b = a + b を使用すると、関数の最初の引数の部分適用である関数を定義できます。

let sum a b = a + b

let addTen = sum 10
let result = addTen 95
// Result is 105.

パラメーターとしてタプルを使用すると、カリー化が無効になります。 詳細については、「関数」の「引数の部分適用」を参照してください。

タプル型の名前

タプルである型の名前を記述する場合は、* 記号を使用して要素を区切ります。 (10, 10.0, "ten") のように、intfloatstring で構成されるタプルの場合、型は次のように記述されます。

int * float * string

構造体タプル型の型エイリアスを作成する場合は、外側のかっこは必須であることに注意してください。

type TupleAlias = string * float
type StructTupleAlias = (struct (string * float))

C# タプルとの相互運用

C# 7.0 で、この言語にタプルが導入されました。 C# のタプルは構造体であり、F# の構造体タプルと同等です。 C# と相互運用する必要がある場合は、構造体タプルを使用する必要があります。

これは簡単に行うことができます。 たとえば、タプルを C# クラスに渡して、その結果 (これも同様にタプル) を使用する必要があるとします。

namespace CSharpTupleInterop
{
    public static class Example
    {
        public static (int, int) AddOneToXAndY((int x, int y) a) =>
            (a.x + 1, a.y + 1);
    }
}

F# コードでは、構造体タプルをパラメーターとして渡し、その結果を構造体タプルとして使用できるようになります。

open TupleInterop

let struct (newX, newY) = Example.AddOneToXAndY(struct (1, 2))
// newX is now 2, and newY is now 3

参照タプルと構造体タプルの間の変換

参照タプルと構造体タプルの基になる表現はまったく異なるため、暗黙的に変換することはできません。 つまり、次のようなコードはコンパイルされません。

// Will not compile!
let (a, b) = struct (1, 2)

// Will not compile!
let struct (c, d) = (1, 2)

// Won't compile!
let f(t: struct(int*int)): int*int = t

1 つのタプルに対してパターン マッチングを行い、構成要素を使用してもう一方を構築する必要があります。 次に例を示します。

// Pattern match on the result.
let (a, b) = (1, 2)

// Construct a new tuple from the parts you pattern matched on.
let struct (c, d) = struct (a, b)

参照タプルのコンパイルされた形式

このセクションでは、タプルがコンパイルされている場合の形式について説明します。 こちらに記載されている情報は、.NET Framework 3.5 以下を対象としている場合を除き、読む必要はありません。

タプルはコンパイルされるといくつかのジェネリック型 (すべて System.Tuple という名前) の 1 つのオブジェクトになります。これは、アリティ、つまり型パラメーターの個数によってオーバーロードされます。 タプル型は、C# や Visual Basic などの別の言語から表示する場合や、F# コンストラクトを認識しないツールを使用する場合に、この形式で表示されます。 Tuple 型は .NET Framework 4 で導入されました。 以前のバージョンの .NET Framework を対象としている場合、コンパイラでは、F# コア ライブラリの 2.0 バージョンの System.Tuple のバージョンが使用されます。 このライブラリの型は、.NET Framework の 2.0、3.0、3.5 の各バージョンを対象とするアプリケーションにのみ使用されます。 型の転送は、.NET Framework 2.0 と .NET Framework 4 F# のコンポーネント間のバイナリ互換性を確保するために使用されます。

構造体タプルのコンパイルされた形式

構造体タプル (たとえば、struct (x, y)) は、参照タプルとは基本的に異なります。 これらは ValueTuple 型にコンパイルされます。これは、アリティ、つまり型パラメーターの個数によってオーバーロードされます。 これらは、C# 7.0 タプルおよびVisual Basic 2017 タプルと同等のものであり、双方向の相互運用が可能です。

関連項目