3つの引数を持つ関数
VBAHaskellで3つ以上の引数を持つ関数をファンクタ化したい。 APIのレベルでそれをサポートする気は今のところないので、VBA側で簡易的な対応をした。
Haskell_1_Core.bas にそれをサポートする関数 make_funPointer_with_3_parameters を追加した。
'ユーザ関数をbindファンクタ化する(3つのパラメータを持つ関数) Function make_funPointer_with_3_parameters(ByVal func1 As LongPtr, _ ByVal func2 As LongPtr, _ ByVal func3 As LongPtr, _ ByRef firstParam As Variant, _ ByRef secondParam As Variant, _ ByRef thirdParam As Variant) As Variant If Is_Missing_(firstParam) Or is_placeholder(firstParam) Then make_funPointer_with_3_parameters = _ VBA.Array(func1, _ IIf(Is_Missing_(firstParam), placeholder, firstParam), _ VBA.Array(secondParam, thirdParam), _ placeholder _ ) ElseIf Is_Missing_(secondParam) Or is_placeholder(secondParam) Then make_funPointer_with_3_parameters = _ VBA.Array(func2, VBA.Array(firstParam, thirdParam), _ IIf(Is_Missing_(secondParam), placeholder, secondParam), _ placeholder _ ) ElseIf Is_Missing_(thirdParam) Or is_placeholder(thirdParam) Then make_funPointer_with_3_parameters = _ VBA.Array(func3, _ VBA.Array(firstParam, secondParam), _ IIf(Is_Missing_(thirdParam), placeholder, thirdParam), _ placeholder _ ) Else make_funPointer_with_3_parameters = Empty End If End Function
少しややこしいので、ファイルをコピーする簡単な関数 copyFile で説明する。
copyFile はコピー先フォルダ、コピー元フォルダ、ファイル名を指定してファイルをコピーするだけだが、これまで vbaHaskell では扱っていなかった3パラメータ関数だ。
これを vbaHaskell の mapF に渡すと次のようなことができる。
- 複数のコピー先フォルダを指定する(バックアップ等で複数の場所にコピーする時など)
- mapF(p_copyFile( , コピー元フォルダ, ファイル名 ), コピー先フォルダ配列)
- 複数のファイルを指定する(全ファイルをコピーするなど)
- mapF(p_copyFile( コピー先フォルダ, コピー元フォルダ ), ファイル名配列)
(コピー元フォルダを複数指定するのはこの場合意味がない)
mapF で実際に呼ばれているのは3通りの補助関数のどれかで、それらは従来通りの2変数関数である。つまり3変数関数と言ってもそのうち2つを配列にパックしているだけのことだ。
' //ファイルのコピー Function copyFile(ByVal targetDirectory As String, _ ' //コピー先フォルダ ByVal sourceDirectory As String, _ ' //コピー元フォルダ ByVal fileName As String) As Long ' //ファイル名 copyFile = 0 Dim fso As Object Set fso = CreateObject("Scripting.FileSystemObject") On Error GoTo myError fso.copyFile sourceDirectory & "\" & fileName, targetDirectory & "\" & fileName, True copyFile = 1 myError: Set fso = Nothing End Function ' //ファンクタ化する Function p_copyFile(Optional ByRef firstParam As Variant, _ Optional ByRef secondParam As Variant, _ Optional ByRef thirdParam As Variant) As Variant p_copyFile = make_funPointer_with_3_parameters( _ AddressOf copyFile_partial1, _ AddressOf copyFile_partial2, _ AddressOf copyFile_partial3, _ firstParam, _ secondParam, _ thirdParam) End Function ' //どの引数をプレースホルダにするかによって3通りの補助関数を作る ' //第1引数(コピー先フォルダ)をプレースホルダにする Private Function copyFile_partial1(ByRef target As Variant, ByRef source_fname As Variant) As Variant copyFile_partial1 = copyFile(target, source_fname(0), source_fname(1)) End Function ' //第2引数(コピー元フォルダ)をプレースホルダにする Private Function copyFile_partial2(ByRef target As Variant, ByRef source_fname As Variant) As Variant copyFile_partial2 = 0 ' こんなコピーは無理 End Function ' //第3引数(ファイル名)をプレースホルダにする Private Function copyFile_partial3(ByRef target_source As Variant, ByRef fname As Variant) As Variant copyFile_partial3 = copyFile(target_source(0), target_source(1), fname) End Function