紹介記事の補足
t-homさんがVBAHaskellの紹介記事を書いてくれた。
thom.hateblo.jp
こんなことは僕の人生初なので、とてもうれしい。
ところでそこにapplyFun2by2
関数が取り上げられていて少し驚いた。マイナーな関数だと思っていたからだ。t-homさんにはQiitaでも「before-afterで見せるとわかりやすいのでは?」という旨のコメントをいただいているので、さっそくこれをビフォー/アフターしてみたい。
まず、紹介されていたコードはこうだ。数値の列に演算を施すときに、演算そのものも引数として指定できるよ、という例になっている。
Sub TestVBAHaskell版() Call 計算(p_plus, 1000, 20, 3, 9) Call 計算(p_minus, 1000, 20, 3, 9) Call 計算(p_mult, 1000, 20, 3, 9) Call 計算(p_divide, 1000, 20, 3, 9) End Sub Sub 計算(Ope As Variant, ParamArray x()) Dim total As Variant Dim i As Long total = x(0) For i = 1 To UBound(x) total = applyFun2by2(Array(total, x(i)), Ope) ' ← ここ Next Debug.Print total End Sub
このSub TestVBAHaskell版
を実行すると、
1032
968
540000
1.85185185185185
と出力される。それぞれ
1000 + 20 + 3 + 9
1000 - 20 - 3 - 9
1000 * 20 * 3 * 9
1000 / 20 / 3 / 9
の計算結果である。
'applyFun2by2'は「2変数関数に2つの要素からなる配列を渡す」ときに使う関数であり、上のapplyFun2by2(Array(total, x(i)), Ope)
は、意味的には Ope(total, x(i))
である。これを少し別な書き方をするとこうなる。
Sub TestVBAHaskell版2() Call 計算2(p_plus, 1000, 20, 3, 9) Call 計算2(p_minus, 1000, 20, 3, 9) Call 計算2(p_mult, 1000, 20, 3, 9) Call 計算2(p_divide, 1000, 20, 3, 9) End Sub Sub 計算2(Ope As Variant, ParamArray x()) Dim total As Variant Dim i As Long total = x(0) For i = 1 To UBound(x) total = applyFun(x(i), bind1st(Ope, total)) ' ← ここ Next Debug.Print total End Sub
bind1st
は「2変数関数の1番目の引数を束縛する」関数で、Ope(total, _ )
のプレースホルダである _ のところに実引数が繰り返し読み込まれる挙動となる。
だが、これらはどちらもVBAHaskellらしいコードではなく、2変数関数を繰り返し適用するのはfold系の関数を使うのが一番ラクだ。ループを書かずに済ませるのがVBAHaskellのもともとの目標でもあったし。
Sub TestVBAHaskell版3() Call 計算3(p_plus, 1000, 20, 3, 9) Call 計算3(p_minus, 1000, 20, 3, 9) Call 計算3(p_mult, 1000, 20, 3, 9) Call 計算3(p_divide, 1000, 20, 3, 9) End Sub Sub 計算3(Ope As Variant, ParamArray x()) Dim tmp As Variant tmp = x Debug.Print foldl1(Ope, tmp) ' ← ここ End Sub
foldl1
は「たたみ込み関数」というものの1パリエーションで、リストの先頭の値を初期値として使って左から順に関数を適用していくものだ。
意味的にはこういう感じになる。
foldl1(p_plus, Array(1,2,3,4,5)) → 1 + 2 + 3 + 4 + 5
foldl1(p_Func, Array(1,2,3,4,5)) → Func(Func(Func(Func(1, 2), 3), 4,) 5)
なお、上のコードで
tmp = x
と、わざわざコピーを作っているのにはわけがあって、ParamArray で受け取った配列はこうするしかないのだ。この事情は
に書いた。