C# の例(14)
続いて「仮想サーバー」の NumbersServer クラスについても考えていきます。「仮想サーバー」が状態を持たないとします。
このクラスにも時刻 time を導入して、時刻 time ごとに「仮想サーバー」が存在すると考えます。「仮想ブラウザー」では NextNumbers メソッドで時刻 time の値を取得して、計算を行った結果を次の時刻の値として NextNumbers メソッドで返却するようにしたいのですが、現在はそうなっていません。NextNumbers メソッドは null を受け取ったときは最初の値を返却し、それ以外のときは受け取った値をそのまま返すようになっています。本来は、NextNumbers メソッドで受け取った値が GenerateDecimalServer に反映されなければいけないのですが、そうなっていません。しかし参照透過性がある場合はこれでも同じ結果となります。「仮想サーバー」が状態を持たないとしたので、その場合はどのようにするか検討しなくてはいけません。
「仮想ブラウザー」が複数あってその計算の結果が異なるとして、そのうちの一つが「仮想サーバー」に反映される場合も検討する必要があります。
internal class NumbersServer { public NumbersServer(int time) { generator_server = GenerateDecimalServer(time).GetEnumerator(); // yield用 generator_server.MoveNext(); // yield用 } private IEnumerator<Numbers> generator_server; private Numbers? current_numbers; public Numbers NextNumbers(Numbers current) { if (current == null) { LongDecimal number = new LongDecimal(); LongDecimal square_difference = new LongDecimal(3); Numbers nums = new Numbers(number, square_difference, 0); return nums; } return current; } // 時刻 time のときの値を返すバージョン public IEnumerable<Numbers> GenerateDecimalServer(int time) { IEnumerable<Numbers> RepeatByTime(Numbers nums, int t, int time) { if (t < time) { Tuple<int, Numbers> d_ns = nums.GetNextDecimalDigitAndNumbers(); return ImmutableList<Numbers>.Empty.Add(nums).AddRange(RepeatByTime(d_ns.Item2, t + 1, time)); } return ImmutableList<Numbers>.Empty; } LongDecimal number = new LongDecimal(); LongDecimal square_difference = new LongDecimal(3); Numbers nums = new Numbers(number, square_difference, 0); return RepeatByTime(nums, 0, time); } }
Calc クラスの RepeatServer は以下のようになります。
public string RepeatServer() { LongDecimal repeat(LongDecimal number, int e, int count, Numbers current) { if (e < count) { Numbers numbers = generator_server.NextNumbers(current); Tuple<int, Numbers> d_ns = numbers.GetNextDecimalDigitAndNumbers(); int dd = d_ns.Item1; return repeat(number + new LongDecimal(dd).Shift(e), e + 1, count, d_ns.Item2); } else { return number; } } LongDecimal result_number = repeat(new LongDecimal(), 0, count, null); return result_number.Print(); }