LoginSignup
0
0

More than 5 years have passed since last update.

VBAHaskellの紹介 その7 (bind1stとbind2nd)

Last updated at Posted at 2015-04-30

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

VBAHaskellにbind1stbind2ndを追加した。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


  1. ヘルパ関数 make_funPointer を使って作れる 

  2. 32bit Officeだから。まだ64bit対応はできていない。 

  3. 記述に誤りがあったので訂正:2015/5/17 

  4. Haskell_4_vectorモジュール 

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