t-hom’s diary

主にVBAネタを扱っているブログ…とも言えなくなってきたこの頃。

関数型言語 MAPとは何か

今回は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という同等の関数が使える。

github.com

以下、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を使うときは、下層で行われている「それぞれに」のイメージを捨てて、「集合に関数をマッピングさせて、別の集合を作る」という大枠で考えることが大事かなと思う。

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。