今回はVBAネタではない。
とあるブログにmapとeachで混乱したと書かれていたので、ちょっとネットで調べてみたところ、結構違いがわからないという意見もある模様。
VBAにmapに相当する機能は無いけれど、一般的なプログラミングの知識として役立つかなと思ったので紹介しておこうと思う。
関数型言語には、map関数というものがある。
これはマッピング、つまり「対応付け」を行う関数である。
ある集合Aに対し、関数Xを対応付けた別の集合Bを作るという使い方をする。
例えば整数のリスト[1 2 3 4 5 6 7 8 9]に対し、引数に+1して返す関数をマッピングすると、
[2 3 4 5 6 7 8 9 10]というリストが生まれる。
VBAで説明しろと言われても標準機能でmapは無いのだが、mmYYmmddさんが公開されているVBAHaskellを使うとmapFという同等の関数が使える。
以下、VBAHaskellを使って書いたコード
Sub mapTest() Dim Arr() As Variant '1~5までを格納した配列に、5を足す関数をマッピングしている。 Arr = mapF(p_plus(5), Array(1, 2, 3, 4, 5)) '出力 For Each n In Arr Debug.Print n Next End Sub
結果は次のように表示される。
6 7 8 9 10
上記のコードではArray(1, 2, 3, 4, 5)に対して、p_plus(5)をマッピングさせてArrを作っている。
対して、For Eachなどで出てくるEachとは、「それぞれに」という意味がある。
各要素に対して処理を行うのがFor Each、集合に対して関数を適合させるのがMapということになる。
ここでややこしいのが、Mapも結局中身の処理としては「それぞれの要素」に対して処理を行っているということ。
だからMapにできることはEachにもできてしまう。
しかしMapは集合を作ることに特化しているが、Eachは集合の作成に限ったことではない。
私は、MapとEachの違いは、抽象度の違いであると思う。
【参考】
thom.hateblo.jp
VBA使いにとってもうすこし身近な例でいうと、たとえば、ループ処理というのはコンピューターの内部ではジャンプ処理として実装されている。
【参考】
thom.hateblo.jp
人間にとってわかりやすいように「ループとしてのジャンプ」が、「ループ命令」として抽象化されているのだ。
また、分岐命令も、関数呼び出しも本当はジャンプ命令なのだが、それぞれIf文、Call文などとして抽象化されている。
それと同じように、Mapというのは、Each文で各要素に関数を適用していく処理を「マッピング命令」として抽象化したものだと思う。
ポイントは、Each文は集合を作ることに特化していないこと。Each文はあくまで「それぞれに」何かをする文である。
逆にmapを使うときは、下層で行われている「それぞれに」のイメージを捨てて、「集合に関数をマッピングさせて、別の集合を作る」という大枠で考えることが大事かなと思う。