1. 概要

場合によっては、関連している場合と関連していない場合がある複数の要素をグループ化する方法が必要になります。 このシナリオでは、タプルを使用できます。これは、さまざまなタイプのオブジェクトの順序付けられたコレクションです。

前のチュートリアルでは、Javaでタプルをサポートするjavatuplesと呼ばれる優れたサードパーティライブラリを確認しました。 ありがたいことに、 Scala にはすでにタプル型が組み込まれています。これは、さまざまな型の最大22個の要素を保持するために使用できる不変のデータ構造です。

このクイックチュートリアルでは、Scalaでタプルを作成する方法、その要素にアクセスする方法、最も重要なメソッドのいくつかを確認し、それらをいつ使用するかについて説明します。

2. タプルの作成

タプルの作成は非常に簡単で、ボイラープレートコードは必要ありません。 要素を括弧で囲むだけです

val tuple: (String, Int) = ("Joe", 34)

ここでは、String要素とInt要素を含むタプルを作成しました。 矢印構文を使用してそれらを作成することも可能です。

val stillTuple: (String, Int) = "Joe" -> 34

Scalaでは、タプルは Tuple2 Tuple3からTuple22までの一連のクラスを使用して定義されます。 実際には、これらのクラスを直接使用する必要はおそらくないでしょうが、内部で何が起こっているのかを知ることは興味深いことです。

さらにいくつかの要素を持つタプルを作成する方法を簡単に見てみましょう。

val tuple3: (String, Int, Boolean) = ("Joe", 34, true)
val tuple4: (String, Int, Boolean, Char) = ("Joe", 34, true, 'A')

(String、Int、Boolean)は、Tuple3 [String、Int、Boolean]の単なる構文糖衣であることに注意してください。

次のセクションでは、タプル内の要素にアクセスする方法を見ていきます。

3. 要素へのアクセス

タプル内の要素には、2つの方法のいずれかでアクセスできます。 最初のアプローチは、アンダースコア構文を使用して位置ごとに要素にアクセスすることです。

たとえば、 _1 メソッドを使用して最初の要素にアクセスし、 _2 を使用して2番目の要素にアクセスすることができます(最大22)。

val name = tuple._1 
val age = tuple._2

パターンマッチングを使用して、複数の変数変数にタプルを割り当てることもできます。

val (userName, userAge) = tuple

ここでは、タプルを分解し、最初の要素をuserNameという変数に割り当てます。この変数の推定型は Stringです。同様に、2番目の要素をuserAgeという変数に割り当てます。 推定タイプのInt

必要な場所でアンダースコアを使用して変数を宣言するときに、一部の要素を省略することもできます。

val (_, myAge) = tuple

4. 典型的なユースケース

タプルは、関数から複数の値を返す必要がある場合、または関数に複数の値を渡す必要がある場合に特に役立ちます。 特に無関係な値を返す必要がある場合は、caseクラスを使用する代わりにこれが望ましい場合があります。

4.1. 複数の値を返す

タプルを返す特に良い例は、partitionメソッドです。

def partition[A](xs: List[A])(predicate: A => Boolean): (List[A], List[A]) = {
  xs.foldRight((List.empty[A], List.empty[A])) {
    case (a, (lefts, rights)) =>
      if (predicate(a)) (a :: lefts, rights) else (lefts, a :: rights)
  }
}
val (evens, odds) = partition(List(1, 3, 4, 5, 2))(_ % 2 == 0)

この例では、 partition メソッドはListのペアを返します。最初のリストは特定の述語を満たすすべての要素で構成され、2番目のリストは満たさないすべての要素で構成されます。

4.2. 複数の値を渡す

同様に、タプルを使用して、複数のパラメーターを1つのパラメーター関数に渡すこともできます。 複数のパラメーターを持つ関数を、唯一の引数としてタプルを受け入れる関数に変換する特別なtupledメソッドもあります。

val data = Map(
    "Joe" -> 34,
    "Mike" -> 16,
    "Kelly" -> 21
  )

case class User(name: String, isAdult: Boolean)

val createUser: (String, Int) => User = (name, age) => User(name, age >= 18)
val users = data.map(createUser.tupled)

上記の例では、 createUser 関数を使用して、dataマップをUserクラスに変換します。 .tupled メソッドを呼び出すのを忘れると、次のエラーで失敗します。

type mismatch; 
found : (String, Int) => User 
required: ((String, Int)) => ? 
val users = data.map(createUser)

コンパイラはタプルパラメータを持つ1つの引数関数が必要な場所に2つの引数関数を渡そうとしていると言っています。

5. 結論

このクイックチュートリアルでは、Scalaでタプルタイプを紹介しました。 タプルを作成する方法と、タプルオブジェクト内の値にアクセスする方法を学びました。 また、いくつかの便利な方法を確認し、いくつかの典型的な使用例を説明しました。

いつものように、記事の完全なソースコードは、GitHubから入手できます。