ランダムな関数実行
Mochikit を使って、複数の関数をランダムに呼ぶ関数、というのを作ってみました。
function randcall(/*f1, f2, f3...*/) { var f = partial(compose(next, irand), arguments); return function() { return f().apply(this, arguments); }; }
短い中に Mochikit の関数的な要素を活用しています。まず関数合成 (compose) と引数の部分適用 (partial) を組み合わせて
next(irand(arguments))
を実行する手前の状態を作っています (f)。
"irand" は配列 (的なもの) をランダムに取り出すイテレータで、mala さんによる実装を Mochikit 用に移植したものです (省略します) 。
それに "next" 関数を適用することで「引数をランダムに一つだけ取り出す」という操作を行うわけです。さらに "partial" で予め "irand" への引数を固定しています。
スコープをまたいで arguments オブジェクト (関数のリスト) を利用しているわけですが、arguments を別の変数に割り当てておく必要はありません。partial の有効な利用法と言えるでしょう。
返り値は、任意の引数を、ランダムにピックアップした関数に渡す、という関数です。
さて、作ってはみたものの、用途があまり思い浮かびません (笑。
が、例えばある出力関数が複数の出力先を取れる場合に、それぞれの出力先にバインドした関数を渡しておき、ランダムな場所に出力させる、という使い方が可能だと思います (ここで言う「出力先」には DOM 要素や配列等が考えられます)。
例として気まぐれな配列 push の使用例をアレンジしたものをお見せします。
例 1 (ある配列のデータを三つの配列に振り分ける):
function pusher(a) { return function(x) { a.push(x); }; } var a = [], pa = pusher(a); var b = [], pb = pusher(b); var c = [], pc = pusher(c); forEach( large_list, randcall(pa, pb, pc) );
例 2 (同様に、データを三つの配列に振り分ける):
// 略 var rc = randcall(pa, pb, pc); responseText.replace(/<a href="(.+?)"/g, function(_, $1) { rc($1); });
あ、じゃんけんのプログラムも作れそうですね。