t-hom’s diary

主にVBAネタを扱っているブログです。

【紹介記事】ジャグ配列を展開(VBAHaskell版)

mmYYmmddさんにて、以下の記事が公開された。mmyymmdd.hatenablog.com

「フラットな配列」
いい表現である。これは一本とられたな。

さて、VBAHaskell版について紹介していこう。

そもそもVBAHaskellとは何かというのは以下の過去記事を参照してほしい。thom.hateblo.jp


VBAHaskellを使って書いたジャグ配列の展開は、どうやらイテレータと畳み込み(Fold)を使った手法のようで、こちらもメインコードはスッキリまとまっている。

しかし。。。

関数型の素養が低い私にはちょっと難しかった。

そこで、まず訳してみることにした。

'以下、mmYYmmddさんのコード(勝手に日本語訳版)
'著作権は元作者のmmYYmmddさんにあります。
'http://mmyymmdd.hatenablog.com/entry/2015/08/21/004529

Function 畳み込み再帰(ByRef 反復子 As Variant, ByRef x As Variant) As Variant
    If IsArray(x) Then
        畳み込み再帰 = foldl(p_畳み込み再帰, 反復子, x)  ' ← ここ
    Else
        畳み込み再帰 = iterator_push_ex(反復子, x)     ' 単純に末尾に追加
    End If
End Function
    ' この関数を関数ポインタ化したもの
    Function p_畳み込み再帰(Optional ByRef firstParam As Variant, Optional ByRef secondParam As Variant) As Variant
        p_畳み込み再帰 = make_funPointer(AddressOf 畳み込み再帰, firstParam, secondParam)
    End Function

'以下プロシージャはイジったので、元コードと異なる。
'※代入を減らしてより宣言的にしようとしたため。
' VBAHaskellの内部処理があまり分かってないので、
' パフォーマンス等が犠牲になっている可能性あり。

Sub ジャグ配列をフラットな配列に展開()

    Dim ジャグ配列: ジャグ配列 = Array(1, Array(2, Array(3, Array(4, Array(5), 6))), 7)
    
    Dim 反復子: 反復子 = _
        畳み込み再帰( _
            make_iterator(Array()), _
            ジャグ配列)

    Dim フラットな配列: フラットな配列 = release_iterator(反復子)
    ReDim Preserve フラットな配列(0 To iterator_pos(反復子))
    
    '配列のサイズ
    printS フラットな配列
    
    '配列の内容
    printM フラットな配列
End Sub

コード中に使用されている以下のワードはVBAHaskellのプロシージャである。


確かに、Foldに関数ポインタを渡す理屈は分かるが、通常の再帰と比べたメリットはいまひとつ分からない。
このコードを正確に理解するにはもう少し関数型を学ぶ必要があると思った。

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。