9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

t._1 は読みにくい... タプルの要素のアクセスの可読性を上げる方法 【Scala】

Posted at
val t = (1, "Mike", 1000)
val name = t._2

println(name) // Mike

ここでの t._2 のような要素のアクセスは読みにくい.
この程度のコード量なら問題ないかもしれないが, タプルの種類が増えたり, 要素が増えると読むのが辛くなるのでどうにかしたい.

要約

パターンマッチを駆使しよう.

パターンマッチを使った代入で可読性を上げる

つまりこういうこと.

val t = (1, "Mike", 1000)
// val name = t._2
val (_, name, _) = t

println(name) // Mike

使わない部分はアンダースコアで捨てるとよい.

タプルのシーケンスの場合

素直に書くとこうなるだろう.

val data = Seq((1, "Mike", 1000), (2, "Harvey", 1500), (3, "Louis", 2000))

data.foreach(t => println(t._2)) // Mike Harvey Louis

これをパターンマッチを使って読みやすくしてみる.

val data = Seq((1, "Mike", 1000), (2, "Harvey", 1500), (3, "Louis", 2000))

data.foreach { case (_, name, _) => println(name) } // Mike Harvey Louis

Pattern Matching Anonymous Function というものらしい. (たぶん)

もちろん for-yield の中でも以下のようにできる.

val data = Seq((1, "Mike", 1000), (2, "Harvey", 1500), (3, "Louis", 2000))

val names = for { (_, name, _) <- data } yield name // names: Seq[String] = List(Mike, Harvey, Louis)

Slick での例

筆者は ORM の Slick を用いるときにこのテクニックをよく使う.

// Dramas, Episodes, Comments は slick-codegen で DB のスキーマから生成された TableQuery
val query = for {
  ((drama, episode), comment) <-
      Dramas
        .filter(_.title === "Suits")
        .join(Episodes)
        .join(Comments)
        .on {
          case ((drama, episode), comments) =>
            drama.id === episode.dramaId && episode.id === comments.episodeId
        }
        .sortBy { case ((_, episode), _) => episode.season }
} yield (drama, episode, character)

例えばソートするところは

.sortBy(_._1._2.season)

と同じだが, どちらが読みやすいかは明白だろう.

補足

タプルが何かしらのまとまりならクラスを使う

そもそもそのタプルが「意味のあるかたまり」ならクラスでまとめておいた方がいい.

case class Character(id: Int, name: String, asset: Int)

val c = Character(1, "Mike", 1000)
println(c.name) // Mike

val data = Seq(Character(1, "Mike", 1000), Character(2, "Harvey", 1500), Character(3, "Louis", 2000))
data.foreach(c => println(c.name)) // Mike Harvey Louis

参考

9
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?