遅延評価と無限リスト

遅延評価で遊んでみる。

using System;
using Nemerle;

#if false
// 遅延評価を使わない場合
class Range {
  public Val : int;
  public Next : Range;

  public this (begin : int, step : int) {
    Val = begin;
    // コンストラクタが再帰的に呼ばれ、最終的にはスタックオーバーフロー
    Next = Range (begin + step, step);
  }
}
#endif

class Range {
  public Val : int;
  public Next : LazyValue [Range];

  public this (begin : int, step : int) {
    Val = begin;
    // Nextの値は実際に使われるまで評価されない
    // つまり、この時点ではNextオブジェクトのコンストラクタは呼ばれない
    Next = lazy (Range (begin + step, step));
  }
}

mutable range = Range (0, 7);

repeat (20) {
  Console.Write ($"$(range.Val),");
  // この時点でNextオブジェクトのコンストラクタが評価される
  // しかし、次のNextオブジェクトのコンストラクタは評価されないのでスタックオーバーフローにはならない
  range = range.Next;
}

/* 結果
0,7,14,21,28,35,42,49,56,63,70,77,84,91,98,105,112,119,126,133,
 */

遅延評価を使うとこのように、無限リストが簡単に実現できます。なんか面白いですね。

あと、トップレベルで式を使った場合にclassやmoduleが使えなかったのが改善されているみたいです。