LoginSignup
2
0

More than 3 years have passed since last update.

Mapはただの連想配列ではない、PartialFunctionでもあることを知っているか?

Posted at

背景

ある日、下記のコードがなぜ動くのか理解できなかった。

val a = Map(1 -> "one", 2 -> "two")
val b = Option(1)
val x = b.collect(a)
println(x) // Some("one")

そもそもなぜこんなことをしたのかは割愛。

collectの認識

collectはfilterとmapが混じったものという認識でした。
下記のようなコードの風に使うんだなと。

class Person(val name: String, val age: Int)
val a = Seq(new Person("a", 10), new Person("b", 20), new Person("c", 30))
// 下二つは同じ
val b = a.collect{case person if(person.age > 15) => person.name}
val c = a.filter(_.age > 15).map(_.name)

println(b) // Seq("b", "c")
println(c) // Seq("b", "c")

見えてなかった本質

本質は別にあって、collectは引数にpartialfunctionを受け取る関数なんだと!
partialfunctionとはなんぞやということなんやが、以下が簡単なpartialfunctionの例です。
partialfunctionを使うときは型宣言は省略することはできなくて省略すると怒られます。

val pf: PartialFunction[Int, String] = {case 5 => "五"}
val c = pf(5)
val d = pf(6)
println(c) // "五"
println(d) // match error

みたまんまで、マッチする場合のみ処理を行う関数のことを指します。だから部分関数なんですね。

ここで本題に戻りますが、なんとMapはこのpartialfunctionをmixInしております。

val a = Map(1 -> "one", 2 -> "two")
val b = a(1)
println(b) // "one"

このMapからキーを与えて値をとるこの動きがまさに部分関数な訳です。
それにあったキーのみ値を返す動きをするのがmixInしている理由な訳ですね。
このようなことからMap自身がpartialfuncitonとなり、collectの引数に渡せるのだと。。scala面白え。

余談

MapでできるのであればSeqでも。。

val seq = Seq("zero", "one", "two")
val collected = Option(0).collect(seq)
println(collected) // Some("zero")

できた。面白い。

2
0
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
2
0