エレファント・コンピューティング調査報告

極限に関する順序を論理プログラミングの手法を使って指定することを目指すブロクです。

関数プログラミングと無限論理多項式(25)

C# の例(9)

Go の例で Numbers 構造体をコピーするようにしましたが、Numbers 構造体の中に返却するための数が含まれているのは気持ち悪いので、これを構造体に含めないようにします。

まず C# の例で考えます。

Numbers クラスから CurrentDigit プロパティと current_digit を削除し、コピーするメソッドを追加します。

        public Numbers Copy()
        {
            return new Numbers(number, square_difference, scale);
        }

unfold に挑戦 - 当面C#と.NETな記録」と「Unfoldの定義および利用例(Python編) - Qiita」に書かれている unfoldr を参考にして、UnfoldL 関数を作成します。UnfoldL は unfoldr とは逆に左から順に関数を適用します。

        private IEnumerable<U> UnfoldL<T, U>(Func<T, Tuple<U, T>> next, T init)
        {
            T src = init;
            for (; ; )
            {
                Tuple<U, T> cpl = next(src);
                // 終了したとき next は null を返すとする
                if (cpl == null)
                {
                    break;
                }
                yield return cpl.Item1;
                src = cpl.Item2;
            }
        }

Calc クラスの Iterate を UnfoldL で置き換えます。

Calc クラスの NextNumbers メソッドを以下の NextDigitAndNumbers メソッドで置き換えます。

        private Tuple<int, Numbers> NextDigitAndNumbers(Numbers numbers)
        {
            Numbers numbers_copy = numbers.Copy();
            int dd = numbers_copy.GetNextDecimalDigit();
            return new Tuple<int, Numbers>(dd, numbers_copy);
        }

Calc クラスの IterateServer メソッドは以下のように UnfoldL を使うように変更します。GetNextDecimalDigit を1回呼び出しているところは削除します。

        public string IterateServer()
        {
            LongDecimal number = new LongDecimal();
            LongDecimal square_difference = new LongDecimal(3);
            Numbers init_numbers = new Numbers(number, square_difference, 0);
            return new LongDecimal(UnfoldL(NextDigitAndNumbers, init_numbers).Take(count)).Print();
        }