VBAHaskellの紹介　その7　（bind1stとbind2nd）

（この記事ははてなブログ　http://mmyymmdd.hatenablog.com/ の再掲です）
2015-04-16

VBAHaskellに**bind1st**と**bind2nd**を追加した。C++の<functional>にあるのとだいたい同じだが、VBAHaskellにおいては関数は初めから何らかの形で束縛されているので、あまり使う場面はないと思う。意味的には引数の"再"束縛なので rebind と名付けるべきなのかもしれない。プレースホルダになっている場所をある値で束縛するわけだが、何が1stで何が2ndかが自分でも少々わかりにくいのだ。

これを説明するために、[VBAHaskellの紹介その5（関数のシグネチャ）](http://qiita.com/mmYYmmdd/items/a89754da3717b7c1e40d)で少し紹介した「関数ポインタ的なもの」についてもっとはっきり示したい。

VBA関数 **func** に対応する **p_func**  [^1]  の実体は次の配列だ。

```vbnet
p_func = Array ( AddressOf  func, _
                 placeholder, _          ' 第1引数のプレースホルダ
                 placeholder, _          ' 第2引数のプレースホルダ
                 placeholder)            ' 関数であるフラグ
```
**`AddressOf  func`**はLong値として扱っている。[^2]　**placeholder**は API で作っている特殊な値で、一種のマジックナンバーと考えてよい。「関数であるフラグ」としても**placeholder** を流用しているが、これは手抜きに過ぎない。別に何でもよかったのだ。

想像できるように、第1引数もしくは第2引数を束縛したものは以下のものになっている。

```vbnet
p_func(3) = Array ( AddressOf func, _
                    3, _               ' 第1引数は3に束縛
                    placeholder, _     ' 第2引数のプレースホルダ
                    placeholder)       ' 関数であるフラグ 

p_func (, 3) = Array ( AddressOf func, _
                       placeholder, _    ' 第1引数のプレースホルダ
                       3, _              ' 第2引数は3に束縛
                       placeholder)      ' 関数であるフラグ
```
bind1stとbind2ndは次のものになる。[^3]

```vbnet
bind1st(p_func(3), 100) = Array ( AddressOf func, _
                                  3          , _  ' 第1引数は変更なし
                                  placeholder, _  ' 第2引数のプレースホルダ
                                  placeholder)    ' 関数であるフラグ  

bind2nd(p_func(3), 100) = Array ( AddressOf func, _
                                3, _             ' 第1引数は変更なし
                                100, _           ' 第2引数は100に束縛
                                placeholder)     ' 関数であるフラグ
```
ややこしいのは関数がネストされた合成関数の場合だ。

```vbnet
p_func(p_func, p_func(, 2)) =
       Array ( AddressOf func, _
               Array ( AddressOf func, placeholder, placeholder, placeholder), _
               Array ( AddressOf func, placeholder, 2, placeholder), _
              placeholder  )
```
これに対して、bind1st や bind2nd を作ったらこういう状態になっている。

```vbnet
bind1st(p_func(p_func, p_func(, 2)) , 3 ) =
     p_func(p_func(3, 3), p_func(, 2)) =
            Array ( AddressOf func, _
              Array ( AddressOf func, 3, 3, placeholder), _
              Array ( AddressOf func, placeholder, 2, placeholder), _
              placeholder
           )

bind2nd(p_func(p_func, p_func(, 2)) , 3 ) =
     p_func(p_func, p_func(3, 2)) =
             Array ( AddressOf func, _
               Array ( AddressOf func, placeholder, placeholder, placeholder), _
               Array ( AddressOf func, 3, 2, placeholder), _
               placeholder
            )
```
 product_set関数 [^4] のパフォーマンスをあげるのにこれらを使った。

\# 2015/5/17 : 関数の内容を文字列化するユーティリティ関数 dumpFun を [Haskell_3_printMモジュール](https://github.com/mYmd/VBA/blob/master/Haskell_3_printM.bas) に追加した。

[VBAHaskellの紹介　その8　（ソート関連）](http://qiita.com/mmYYmmdd/items/dd047d6af8e486465840)
[VBAHaskellの紹介　その6　（foldl）](http://qiita.com/mmYYmmdd/items/e0269141f637f80258d8)
[VBAHaskellの紹介　その1　（最初はmapF）](http://qiita.com/mmYYmmdd/items/c731edf943acc0a0ebe9)

ソースコード https://github.com/mYmd/VBA

[^1]: ヘルパ関数[ make_funPointer ](https://github.com/mYmd/VBA/blob/master/Haskell_1_Core.bas)を使って作れる
[^2]: 32bit Officeだから。まだ64bit対応はできていない。
[^3]: 記述に誤りがあったので訂正：2015/5/17
[^4]: [Haskell_4_vectorモジュール](https://github.com/mYmd/VBA/blob/master/Haskell_4_vector.bas)