(この記事ははてなブログ http://mmyymmdd.hatenablog.com/ の再掲です)
2015-04-16
VBAHaskellにbind1stとbind2ndを追加した。C++のにあるのとだいたい同じだが、VBAHaskellにおいては関数は初めから何らかの形で束縛されているので、あまり使う場面はないと思う。意味的には引数の"再"束縛なので rebind と名付けるべきなのかもしれない。プレースホルダになっている場所をある値で束縛するわけだが、何が1stで何が2ndかが自分でも少々わかりにくいのだ。
これを説明するために、VBAHaskellの紹介その5(関数のシグネチャ)で少し紹介した「関数ポインタ的なもの」についてもっとはっきり示したい。
VBA関数 func に対応する p_func 1 の実体は次の配列だ。
p_func = Array ( AddressOf func, _
placeholder, _ ' 第1引数のプレースホルダ
placeholder, _ ' 第2引数のプレースホルダ
placeholder) ' 関数であるフラグ
AddressOf func
はLong値として扱っている。2 placeholderは API で作っている特殊な値で、一種のマジックナンバーと考えてよい。「関数であるフラグ」としてもplaceholder を流用しているが、これは手抜きに過ぎない。別に何でもよかったのだ。
想像できるように、第1引数もしくは第2引数を束縛したものは以下のものになっている。
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
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) ' 関数であるフラグ
ややこしいのは関数がネストされた合成関数の場合だ。
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 を作ったらこういう状態になっている。
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モジュール に追加した。
VBAHaskellの紹介 その8 (ソート関連)
VBAHaskellの紹介 その6 (foldl)
VBAHaskellの紹介 その1 (最初はmapF)
ソースコード https://github.com/mYmd/VBA
-
ヘルパ関数 make_funPointer を使って作れる ↩
-
32bit Officeだから。まだ64bit対応はできていない。 ↩
-
記述に誤りがあったので訂正:2015/5/17 ↩