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(); }