このブログは、旧・はてなダイアリー「檜山正幸のキマイラ飼育記 メモ編」(http://d.hatena.ne.jp/m-hiyama-memo/)のデータを移行・保存したものであり、今後(2019年1月以降)更新の予定はありません。

今後の更新は、新しいブログ http://m-hiyama-memo.hatenablog.com/ で行います。

サイクリック・カウンター・モナド

/* CyclicCounterMonad.js */

// オペレーション・モノイド
var CounterOp = {
  // モノイド単位
  unit : function() {
    return 0;
  },
  // モノイド乗法
  mult : function(x, y) {
    return x + y;
  }
};

// カウンター・オブジェクト(シングルトン)
var Counter = {
  // 定数
  QUEUE_MODE : 1, // オペレーション・リクエストをキューイング(?)する
  DIRECT_MODE : 0, // オペレーション・リクエストをすぐに実行する

  UPPER_BOUND : 9,
  // LOWER_BOUNDは0に固定する

  // フィールド、ここでは宣言しているだけ、初期化はinitで行う
  _mode : undefined, // 実行モード
  _value : undefined, // 状態値
  _operations : undefined // 累積オペレーション値
};

/* カウンター・リクエストの実行 */
/*
 * ストラテジーを使わずに、Counter内に直接記述
 */

Counter._action_do = function(ops) {
  Counter._value = (Counter._value + ops) % (Counter.UPPER_BOUND + 1);
};

/*  以下にメソッド群 */

Counter.init = function() {
  Counter._mode = Counter.QUEUE_MODE;
  Counter._value = 0;
  Counter._operations = CounterOp.unit();
};

Counter.setMode = function(mode) {
  Counter._mode = mode;
};

Counter.operate = function (op) {
  var old = Counter._operations;
  Counter._operations = CounterOp.mult(old, op);
  if (Counter._mode == Counter.DIRECT_MODE) {
    Counter.execOperations();
  }
};

// キューイング(?)されたオペレーションの実行
Counter.execOperations  = function() {
  var ops = Counter._operations;
  Counter._action_do(ops); // 実行
 // 累積されたカウンタ操作リクエストをクリアする
  Counter._operations = CounterOp.unit();
};

/* 対話的に使用する便利関数 */
/*
 * start()  -- 初期化
 * u()      -- カウントアップ
 * d()      -- カウントダウン
 * x()      -- 溜まっているオペレーション・リクエストの実行
 * q()      -- キュー(?)の表示
 * v()      -- 値の表示
 * qmode(f) -- キューイング(?)するかどうかの設定
 *             fがtrueならキューイング(?)モードになる
 */

// initって名前はナニカとかち合っているようだ(恐い)
function start() {
  Counter.init();
}

function u() {
  Counter.operate("u");
}

function d() {
  Counter.operate("d");
}

function x() {
  Counter.execOperations();
}

function q() {
  return Counter._operations;
}

function v() {
  return Counter._value;
}

function qmode(f) {
  if (f) {
    Counter.setMode(Counter.QUEUE_MODE);
  } else {
    x(); // キュー(?)をフラッシュする
    Counter.setMode(Counter.DIRECT_MODE);
  }
};