LoginSignup
0
0

More than 5 years have passed since last update.

VBAHaskellの紹介 その5 (関数のシグネチャ)

Last updated at Posted at 2015-04-30

(この記事ははてなブログ http://mmyymmdd.hatenablog.com/ の再掲です)
2015-04-12
VBAHaskellはVBAの関数を合成して独立したオブジェクトにしたり、Haskell的なリスト処理をするライブラリだが、それが可能なVBA関数のシグネチャは実質的に1種類しかない。

Function myFunction(ByRef a As Variant, ByRef b As Variant) As Variant
'または
Function myFunction(ByRef a As Variant, Optional ByRef b As Variant) As Variant 

この関数をそのまま使うのではなく、一種の関数ポインタ的なものにして渡す必要があって、それをやるヘルパ関数が
make_funPointermake_funPointer_with_2nd_Default だ。

たとえば Haskell_2_stdFunモジュールで最初に定義されている firstArg 関数はこうなっている。

Function firstArg(ByRef a As Variant, ByRef b As Variant) As Variant
    firstArg = a
End Function
    Function p_firstArg(Optional ByRef firstParam As Variant, _
                                  Optional ByRef secondParam As Variant) As Variant
        p_firstArg = make_funPointer(AddressOf firstArg, firstParam, secondParam)
    End Function

firstArg 関数に付属する p_firstArg が関数ポインタを作っており、その中でmake_funPointerを呼んでいる。関数名は何でもよいが、p_関数名 にだいたい統一している。新たに関数を定義したら、この p_firstArg のコードをコピペして関数名のところだけ対象関数に合わせて修正すれば使えるようになる。1

make_funPointer は4要素の配列を作っているだけで、その配列は(関数ポインタ、引数1、引数2、xxx)という構成になっている。2つある引数には他の関数をネストすることもできて、これによって関数合成が実現される。

C++API側ではこのネストした配列を受け取って頻繁に呼び出すことになるが、VBAのsafearray構造体の中身に毎回アクセスするのは効率が悪いと思われるので、再帰的なリンク構造を再構成してから呼び出すようにしている。具体的には VBA_NestFunc.hpp と VBA_NestFunc.cpp にある funcExpr_i::eval() の再帰的な呼び出しがそれにあたる。

残念ながらここにはコンパイル時処理はない。

VBAHaskellの紹介 その6 (foldl)
VBAHaskellの紹介 その4 (Find)
VBAHaskellの紹介 その3 (FizzBuzz)
VBAHaskellの紹介 その2 (合成関数)
VBAHaskellの紹介 その1 (最初はmapF)

ソースコード:https://github.com/mYmd/VBA
dllバイナリ:http://home.b07.itscom.net/m-yamada/VBA/mapM.dll


  1. ただし元の関数の第2引数がOptional宣言されていて、省略時の動作が定義されている場合は make_funPointer_with_2nd_Default の方を使う方がいい。その例は Haskell_2_stdFun にある対数関数 "logN" で、第2引数が対数の底を表しているが、省略時は自然対数になる。 

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0